xref: /plugin/davcal/helper.php (revision 809cb0fa116ea3a50c13c9b852a3e72d84542c29)
1a1a3b679SAndreas Boehler<?php
2a1a3b679SAndreas Boehler/**
3cb71a62aSAndreas Boehler  * Helper Class for the DAVCal plugin
4a1a3b679SAndreas Boehler  * This helper does the actual work.
5a1a3b679SAndreas Boehler  *
6a1a3b679SAndreas Boehler  */
7a1a3b679SAndreas Boehler
8a1a3b679SAndreas Boehler// must be run within Dokuwiki
9a1a3b679SAndreas Boehlerif(!defined('DOKU_INC')) die();
10a1a3b679SAndreas Boehler
11a1a3b679SAndreas Boehlerclass helper_plugin_davcal extends DokuWiki_Plugin {
12a1a3b679SAndreas Boehler
13a1a3b679SAndreas Boehler  protected $sqlite = null;
14185e2535SAndreas Boehler  protected $cachedValues = array();
15a1a3b679SAndreas Boehler
16a1a3b679SAndreas Boehler  /**
17cb71a62aSAndreas Boehler    * Constructor to load the configuration and the SQLite plugin
18a1a3b679SAndreas Boehler    */
19a1a3b679SAndreas Boehler  public function helper_plugin_davcal() {
20a1a3b679SAndreas Boehler    $this->sqlite =& plugin_load('helper', 'sqlite');
2121d04f73SAndreas Boehler    global $conf;
2221d04f73SAndreas Boehler    if($conf['allowdebug'])
2321d04f73SAndreas Boehler        dbglog('---- DAVCAL helper.php init');
24a1a3b679SAndreas Boehler    if(!$this->sqlite)
25a1a3b679SAndreas Boehler    {
2621d04f73SAndreas Boehler        if($conf['allowdebug'])
2721d04f73SAndreas Boehler            dbglog('This plugin requires the sqlite plugin. Please install it.');
28a1a3b679SAndreas Boehler        msg('This plugin requires the sqlite plugin. Please install it.');
29a1a3b679SAndreas Boehler        return;
30a1a3b679SAndreas Boehler    }
31a1a3b679SAndreas Boehler
32a1a3b679SAndreas Boehler    if(!$this->sqlite->init('davcal', DOKU_PLUGIN.'davcal/db/'))
33a1a3b679SAndreas Boehler    {
3421d04f73SAndreas Boehler        if($conf['allowdebug'])
3521d04f73SAndreas Boehler            dbglog('Error initialising the SQLite DB for DAVCal');
36a1a3b679SAndreas Boehler        return;
37a1a3b679SAndreas Boehler    }
38a1a3b679SAndreas Boehler  }
39a1a3b679SAndreas Boehler
40cb71a62aSAndreas Boehler  /**
41185e2535SAndreas Boehler   * Retrieve meta data for a given page
42185e2535SAndreas Boehler   *
43185e2535SAndreas Boehler   * @param string $id optional The page ID
44185e2535SAndreas Boehler   * @return array The metadata
45185e2535SAndreas Boehler   */
46185e2535SAndreas Boehler  private function getMeta($id = null) {
47185e2535SAndreas Boehler    global $ID;
48185e2535SAndreas Boehler    global $INFO;
49185e2535SAndreas Boehler
50185e2535SAndreas Boehler    if ($id === null) $id = $ID;
51185e2535SAndreas Boehler
52185e2535SAndreas Boehler    if($ID === $id && $INFO['meta']) {
53185e2535SAndreas Boehler        $meta = $INFO['meta'];
54185e2535SAndreas Boehler    } else {
55185e2535SAndreas Boehler        $meta = p_get_metadata($id);
56185e2535SAndreas Boehler    }
57185e2535SAndreas Boehler
58185e2535SAndreas Boehler    return $meta;
59185e2535SAndreas Boehler  }
60185e2535SAndreas Boehler
61185e2535SAndreas Boehler  /**
62185e2535SAndreas Boehler   * Retrieve the meta data for a given page
63185e2535SAndreas Boehler   *
64185e2535SAndreas Boehler   * @param string $id optional The page ID
65185e2535SAndreas Boehler   * @return array with meta data
66185e2535SAndreas Boehler   */
67185e2535SAndreas Boehler  public function getCalendarMetaForPage($id = null)
68185e2535SAndreas Boehler  {
69185e2535SAndreas Boehler      if(is_null($id))
70185e2535SAndreas Boehler      {
71185e2535SAndreas Boehler          global $ID;
72185e2535SAndreas Boehler          $id = $ID;
73185e2535SAndreas Boehler      }
74185e2535SAndreas Boehler
75185e2535SAndreas Boehler      $meta = $this->getMeta($id);
76185e2535SAndreas Boehler      if(isset($meta['plugin_davcal']))
77185e2535SAndreas Boehler        return $meta['plugin_davcal'];
78185e2535SAndreas Boehler      else
79185e2535SAndreas Boehler        return array();
80185e2535SAndreas Boehler  }
81185e2535SAndreas Boehler
82185e2535SAndreas Boehler  /**
8380e1ddf7SAndreas Boehler   * Filter calendar pages and return only those where the current
8480e1ddf7SAndreas Boehler   * user has at least read permission.
8580e1ddf7SAndreas Boehler   *
8680e1ddf7SAndreas Boehler   * @param array $calendarPages Array with calendar pages to check
8780e1ddf7SAndreas Boehler   * @return array with filtered calendar pages
8880e1ddf7SAndreas Boehler   */
8980e1ddf7SAndreas Boehler  public function filterCalendarPagesByUserPermission($calendarPages)
9080e1ddf7SAndreas Boehler  {
9180e1ddf7SAndreas Boehler      $retList = array();
9280e1ddf7SAndreas Boehler      foreach($calendarPages as $page => $data)
9380e1ddf7SAndreas Boehler      {
940b805092SAndreas Boehler          // WebDAV Connections are always readable
950b805092SAndreas Boehler          if(strpos($page, 'webdav://') === 0)
960b805092SAndreas Boehler          {
970b805092SAndreas Boehler              $retList[$page] = $data;
980b805092SAndreas Boehler          }
990b805092SAndreas Boehler          elseif(auth_quickaclcheck($page) >= AUTH_READ)
10080e1ddf7SAndreas Boehler          {
10180e1ddf7SAndreas Boehler              $retList[$page] = $data;
10280e1ddf7SAndreas Boehler          }
10380e1ddf7SAndreas Boehler      }
10480e1ddf7SAndreas Boehler      return $retList;
10580e1ddf7SAndreas Boehler  }
10680e1ddf7SAndreas Boehler
10780e1ddf7SAndreas Boehler  /**
108185e2535SAndreas Boehler   * Get all calendar pages used by a given page
109185e2535SAndreas Boehler   * based on the stored metadata
110185e2535SAndreas Boehler   *
111185e2535SAndreas Boehler   * @param string $id optional The page id
112185e2535SAndreas Boehler   * @return mixed The pages as array or false
113185e2535SAndreas Boehler   */
114185e2535SAndreas Boehler  public function getCalendarPagesByMeta($id = null)
115185e2535SAndreas Boehler  {
116185e2535SAndreas Boehler      if(is_null($id))
117185e2535SAndreas Boehler      {
118185e2535SAndreas Boehler          global $ID;
119185e2535SAndreas Boehler          $id = $ID;
120185e2535SAndreas Boehler      }
121185e2535SAndreas Boehler
122185e2535SAndreas Boehler      $meta = $this->getCalendarMetaForPage($id);
1230b805092SAndreas Boehler
124185e2535SAndreas Boehler      if(isset($meta['id']))
125ed764890SAndreas Boehler      {
126ed764890SAndreas Boehler          // Filter the list of pages by permission
12780e1ddf7SAndreas Boehler          $pages = $this->filterCalendarPagesByUserPermission($meta['id']);
12880e1ddf7SAndreas Boehler          if(empty($pages))
129ed764890SAndreas Boehler            return false;
13080e1ddf7SAndreas Boehler          return $pages;
131ed764890SAndreas Boehler      }
132185e2535SAndreas Boehler      return false;
133185e2535SAndreas Boehler  }
134185e2535SAndreas Boehler
135185e2535SAndreas Boehler  /**
136185e2535SAndreas Boehler   * Get a list of calendar names/pages/ids/colors
137185e2535SAndreas Boehler   * for an array of page ids
138185e2535SAndreas Boehler   *
139185e2535SAndreas Boehler   * @param array $calendarPages The calendar pages to retrieve
140185e2535SAndreas Boehler   * @return array The list
141185e2535SAndreas Boehler   */
142185e2535SAndreas Boehler  public function getCalendarMapForIDs($calendarPages)
143185e2535SAndreas Boehler  {
144185e2535SAndreas Boehler      $data = array();
1454a2bf5eeSAndreas Boehler      foreach($calendarPages as $page => $color)
146185e2535SAndreas Boehler      {
1470b805092SAndreas Boehler            if(strpos($page, 'webdav://') === 0)
1480b805092SAndreas Boehler            {
1490b805092SAndreas Boehler                $wdc =& plugin_load('helper', 'webdavclient');
1500b805092SAndreas Boehler                if(is_null($wdc))
1510b805092SAndreas Boehler                    continue;
1520b805092SAndreas Boehler                $connectionId = str_replace('webdav://', '', $page);
1530b805092SAndreas Boehler                $settings = $wdc->getConnection($connectionId);
1540b805092SAndreas Boehler                $name = $settings['displayname'];
155*809cb0faSAndreas Boehler                $write = $settings['write'];
1560b805092SAndreas Boehler                $calid = $connectionId;
1570b805092SAndreas Boehler            }
1580b805092SAndreas Boehler            else
1590b805092SAndreas Boehler            {
160185e2535SAndreas Boehler                $calid = $this->getCalendarIdForPage($page);
161185e2535SAndreas Boehler                if($calid !== false)
162185e2535SAndreas Boehler                {
163185e2535SAndreas Boehler                    $settings = $this->getCalendarSettings($calid);
164185e2535SAndreas Boehler                    $name = $settings['displayname'];
1650b805092SAndreas Boehler                    //$color = $settings['calendarcolor'];
166ed764890SAndreas Boehler                    $write = (auth_quickaclcheck($page) > AUTH_READ);
1670b805092SAndreas Boehler                }
1680b805092SAndreas Boehler                else
1690b805092SAndreas Boehler                {
1700b805092SAndreas Boehler                    continue;
1710b805092SAndreas Boehler                }
1720b805092SAndreas Boehler            }
173185e2535SAndreas Boehler            $data[] = array('name' => $name, 'page' => $page, 'calid' => $calid,
174ed764890SAndreas Boehler                            'color' => $color, 'write' => $write);
175185e2535SAndreas Boehler      }
176185e2535SAndreas Boehler      return $data;
177185e2535SAndreas Boehler  }
178185e2535SAndreas Boehler
179185e2535SAndreas Boehler  /**
180185e2535SAndreas Boehler   * Get the saved calendar color for a given page.
181185e2535SAndreas Boehler   *
182185e2535SAndreas Boehler   * @param string $id optional The page ID
183185e2535SAndreas Boehler   * @return mixed The color on success, otherwise false
184185e2535SAndreas Boehler   */
185185e2535SAndreas Boehler  public function getCalendarColorForPage($id = null)
186185e2535SAndreas Boehler  {
187185e2535SAndreas Boehler      if(is_null($id))
188185e2535SAndreas Boehler      {
189185e2535SAndreas Boehler          global $ID;
190185e2535SAndreas Boehler          $id = $ID;
191185e2535SAndreas Boehler      }
192185e2535SAndreas Boehler
193185e2535SAndreas Boehler      $calid = $this->getCalendarIdForPage($id);
194185e2535SAndreas Boehler      if($calid === false)
195185e2535SAndreas Boehler        return false;
196185e2535SAndreas Boehler
197185e2535SAndreas Boehler      return $this->getCalendarColorForCalendar($calid);
198185e2535SAndreas Boehler  }
199185e2535SAndreas Boehler
200185e2535SAndreas Boehler  /**
201185e2535SAndreas Boehler   * Get the saved calendar color for a given calendar ID.
202185e2535SAndreas Boehler   *
203185e2535SAndreas Boehler   * @param string $id optional The calendar ID
204185e2535SAndreas Boehler   * @return mixed The color on success, otherwise false
205185e2535SAndreas Boehler   */
206185e2535SAndreas Boehler  public function getCalendarColorForCalendar($calid)
207185e2535SAndreas Boehler  {
208185e2535SAndreas Boehler      if(isset($this->cachedValues['calendarcolor'][$calid]))
209185e2535SAndreas Boehler        return $this->cachedValues['calendarcolor'][$calid];
210185e2535SAndreas Boehler
211185e2535SAndreas Boehler      $row = $this->getCalendarSettings($calid);
212185e2535SAndreas Boehler
213185e2535SAndreas Boehler      if(!isset($row['calendarcolor']))
214185e2535SAndreas Boehler        return false;
215185e2535SAndreas Boehler
216185e2535SAndreas Boehler      $color = $row['calendarcolor'];
217185e2535SAndreas Boehler      $this->cachedValues['calendarcolor'][$calid] = $color;
218185e2535SAndreas Boehler      return $color;
219185e2535SAndreas Boehler  }
220185e2535SAndreas Boehler
221185e2535SAndreas Boehler  /**
222e86c8dd3SAndreas Boehler   * Get the user's principal URL for iOS sync
223e86c8dd3SAndreas Boehler   * @param string $user the user name
224e86c8dd3SAndreas Boehler   * @return the URL to the principal sync
225e86c8dd3SAndreas Boehler   */
226e86c8dd3SAndreas Boehler  public function getPrincipalUrlForUser($user)
227e86c8dd3SAndreas Boehler  {
228e86c8dd3SAndreas Boehler      if(is_null($user))
229e86c8dd3SAndreas Boehler        return false;
230e86c8dd3SAndreas Boehler      $url = DOKU_URL.'lib/plugins/davcal/calendarserver.php/principals/'.$user;
231e86c8dd3SAndreas Boehler      return $url;
232e86c8dd3SAndreas Boehler  }
233e86c8dd3SAndreas Boehler
234e86c8dd3SAndreas Boehler  /**
235185e2535SAndreas Boehler   * Set the calendar color for a given page.
236185e2535SAndreas Boehler   *
237185e2535SAndreas Boehler   * @param string $color The color definition
238185e2535SAndreas Boehler   * @param string $id optional The page ID
239185e2535SAndreas Boehler   * @return boolean True on success, otherwise false
240185e2535SAndreas Boehler   */
241185e2535SAndreas Boehler  public function setCalendarColorForPage($color, $id = null)
242185e2535SAndreas Boehler  {
243185e2535SAndreas Boehler      if(is_null($id))
244185e2535SAndreas Boehler      {
245185e2535SAndreas Boehler          global $ID;
246185e2535SAndreas Boehler          $id = $ID;
247185e2535SAndreas Boehler      }
248185e2535SAndreas Boehler      $calid = $this->getCalendarIdForPage($id);
249185e2535SAndreas Boehler      if($calid === false)
250185e2535SAndreas Boehler        return false;
251185e2535SAndreas Boehler
25251f4febbSAndreas Boehler      $query = "UPDATE calendars SET calendarcolor = ? ".
25351f4febbSAndreas Boehler               " WHERE id = ?";
25451f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $color, $calid);
255185e2535SAndreas Boehler      if($res !== false)
256185e2535SAndreas Boehler      {
257185e2535SAndreas Boehler        $this->cachedValues['calendarcolor'][$calid] = $color;
258185e2535SAndreas Boehler        return true;
259185e2535SAndreas Boehler      }
260185e2535SAndreas Boehler      return false;
261185e2535SAndreas Boehler  }
262185e2535SAndreas Boehler
263185e2535SAndreas Boehler  /**
264cb71a62aSAndreas Boehler   * Set the calendar name and description for a given page with a given
265cb71a62aSAndreas Boehler   * page id.
266cb71a62aSAndreas Boehler   * If the calendar doesn't exist, the calendar is created!
267cb71a62aSAndreas Boehler   *
268cb71a62aSAndreas Boehler   * @param string  $name The name of the new calendar
269cb71a62aSAndreas Boehler   * @param string  $description The description of the new calendar
270cb71a62aSAndreas Boehler   * @param string  $id (optional) The ID of the page
271cb71a62aSAndreas Boehler   * @param string  $userid The userid of the creating user
272cb71a62aSAndreas Boehler   *
273cb71a62aSAndreas Boehler   * @return boolean True on success, otherwise false.
274cb71a62aSAndreas Boehler   */
275a1a3b679SAndreas Boehler  public function setCalendarNameForPage($name, $description, $id = null, $userid = null)
276a1a3b679SAndreas Boehler  {
277a1a3b679SAndreas Boehler      if(is_null($id))
278a1a3b679SAndreas Boehler      {
279a1a3b679SAndreas Boehler          global $ID;
280a1a3b679SAndreas Boehler          $id = $ID;
281a1a3b679SAndreas Boehler      }
282a1a3b679SAndreas Boehler      if(is_null($userid))
28334a47953SAndreas Boehler      {
28434a47953SAndreas Boehler        if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
28534a47953SAndreas Boehler        {
286a1a3b679SAndreas Boehler          $userid = $_SERVER['REMOTE_USER'];
28734a47953SAndreas Boehler        }
28834a47953SAndreas Boehler        else
28934a47953SAndreas Boehler        {
29034a47953SAndreas Boehler          $userid = uniqid('davcal-');
29134a47953SAndreas Boehler        }
29234a47953SAndreas Boehler      }
293a1a3b679SAndreas Boehler      $calid = $this->getCalendarIdForPage($id);
294a1a3b679SAndreas Boehler      if($calid === false)
295a1a3b679SAndreas Boehler        return $this->createCalendarForPage($name, $description, $id, $userid);
296a1a3b679SAndreas Boehler
29751f4febbSAndreas Boehler      $query = "UPDATE calendars SET displayname = ?, description = ? WHERE id = ?";
29851f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $name, $description, $calid);
299b269830cSAndreas Boehler      if($res !== false)
300b269830cSAndreas Boehler        return true;
301b269830cSAndreas Boehler      return false;
302a1a3b679SAndreas Boehler  }
303a1a3b679SAndreas Boehler
304cb71a62aSAndreas Boehler  /**
305cb71a62aSAndreas Boehler   * Save the personal settings to the SQLite database 'calendarsettings'.
306cb71a62aSAndreas Boehler   *
307cb71a62aSAndreas Boehler   * @param array  $settings The settings array to store
308cb71a62aSAndreas Boehler   * @param string $userid (optional) The userid to store
309cb71a62aSAndreas Boehler   *
310cb71a62aSAndreas Boehler   * @param boolean True on success, otherwise false
311cb71a62aSAndreas Boehler   */
312a495d34cSAndreas Boehler  public function savePersonalSettings($settings, $userid = null)
313a495d34cSAndreas Boehler  {
314a495d34cSAndreas Boehler      if(is_null($userid))
31534a47953SAndreas Boehler      {
31634a47953SAndreas Boehler          if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
31734a47953SAndreas Boehler          {
318a495d34cSAndreas Boehler            $userid = $_SERVER['REMOTE_USER'];
31934a47953SAndreas Boehler          }
32034a47953SAndreas Boehler          else
32134a47953SAndreas Boehler          {
32234a47953SAndreas Boehler              return false;
32334a47953SAndreas Boehler          }
32434a47953SAndreas Boehler      }
325a495d34cSAndreas Boehler      $this->sqlite->query("BEGIN TRANSACTION");
326a495d34cSAndreas Boehler
32751f4febbSAndreas Boehler      $query = "DELETE FROM calendarsettings WHERE userid = ?";
32851f4febbSAndreas Boehler      $this->sqlite->query($query, $userid);
329bd883736SAndreas Boehler
330a495d34cSAndreas Boehler      foreach($settings as $key => $value)
331a495d34cSAndreas Boehler      {
33251f4febbSAndreas Boehler          $query = "INSERT INTO calendarsettings (userid, key, value) VALUES (?, ?, ?)";
33351f4febbSAndreas Boehler          $res = $this->sqlite->query($query, $userid, $key, $value);
334a495d34cSAndreas Boehler          if($res === false)
335a495d34cSAndreas Boehler              return false;
336a495d34cSAndreas Boehler      }
337a495d34cSAndreas Boehler      $this->sqlite->query("COMMIT TRANSACTION");
338185e2535SAndreas Boehler      $this->cachedValues['settings'][$userid] = $settings;
339a495d34cSAndreas Boehler      return true;
340a495d34cSAndreas Boehler  }
341a495d34cSAndreas Boehler
342cb71a62aSAndreas Boehler  /**
343cb71a62aSAndreas Boehler   * Retrieve the settings array for a given user id.
344cb71a62aSAndreas Boehler   * Some sane defaults are returned, currently:
345cb71a62aSAndreas Boehler   *
346cb71a62aSAndreas Boehler   *    timezone    => local
347cb71a62aSAndreas Boehler   *    weeknumbers => 0
348cb71a62aSAndreas Boehler   *    workweek    => 0
349cb71a62aSAndreas Boehler   *
350cb71a62aSAndreas Boehler   * @param string $userid (optional) The user id to retrieve
351cb71a62aSAndreas Boehler   *
352cb71a62aSAndreas Boehler   * @return array The settings array
353cb71a62aSAndreas Boehler   */
354a495d34cSAndreas Boehler  public function getPersonalSettings($userid = null)
355a495d34cSAndreas Boehler  {
356bd883736SAndreas Boehler      // Some sane default settings
357bd883736SAndreas Boehler      $settings = array(
358fb813b30SAndreas Boehler        'timezone' => $this->getConf('timezone'),
359fb813b30SAndreas Boehler        'weeknumbers' => $this->getConf('weeknumbers'),
360fb813b30SAndreas Boehler        'workweek' => $this->getConf('workweek'),
3611d5bdcd0SAndreas Boehler        'monday' => $this->getConf('monday'),
3621d5bdcd0SAndreas Boehler        'timeformat' => $this->getConf('timeformat')
363bd883736SAndreas Boehler      );
36434a47953SAndreas Boehler      if(is_null($userid))
36534a47953SAndreas Boehler      {
36634a47953SAndreas Boehler          if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
36734a47953SAndreas Boehler          {
36834a47953SAndreas Boehler            $userid = $_SERVER['REMOTE_USER'];
36934a47953SAndreas Boehler          }
37034a47953SAndreas Boehler          else
37134a47953SAndreas Boehler          {
37234a47953SAndreas Boehler            return $settings;
37334a47953SAndreas Boehler          }
37434a47953SAndreas Boehler      }
37534a47953SAndreas Boehler
37634a47953SAndreas Boehler      if(isset($this->cachedValues['settings'][$userid]))
37734a47953SAndreas Boehler        return $this->cachedValues['settings'][$userid];
37851f4febbSAndreas Boehler      $query = "SELECT key, value FROM calendarsettings WHERE userid = ?";
37951f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $userid);
380a495d34cSAndreas Boehler      $arr = $this->sqlite->res2arr($res);
381a495d34cSAndreas Boehler      foreach($arr as $row)
382a495d34cSAndreas Boehler      {
383a495d34cSAndreas Boehler          $settings[$row['key']] = $row['value'];
384a495d34cSAndreas Boehler      }
385185e2535SAndreas Boehler      $this->cachedValues['settings'][$userid] = $settings;
386a495d34cSAndreas Boehler      return $settings;
387a495d34cSAndreas Boehler  }
388a495d34cSAndreas Boehler
389cb71a62aSAndreas Boehler  /**
390cb71a62aSAndreas Boehler   * Retrieve the calendar ID based on a page ID from the SQLite table
391cb71a62aSAndreas Boehler   * 'pagetocalendarmapping'.
392cb71a62aSAndreas Boehler   *
393cb71a62aSAndreas Boehler   * @param string $id (optional) The page ID to retrieve the corresponding calendar
394cb71a62aSAndreas Boehler   *
395cb71a62aSAndreas Boehler   * @return mixed the ID on success, otherwise false
396cb71a62aSAndreas Boehler   */
397a1a3b679SAndreas Boehler  public function getCalendarIdForPage($id = null)
398a1a3b679SAndreas Boehler  {
399a1a3b679SAndreas Boehler      if(is_null($id))
400a1a3b679SAndreas Boehler      {
401a1a3b679SAndreas Boehler          global $ID;
402a1a3b679SAndreas Boehler          $id = $ID;
403a1a3b679SAndreas Boehler      }
404a1a3b679SAndreas Boehler
405185e2535SAndreas Boehler      if(isset($this->cachedValues['calid'][$id]))
406185e2535SAndreas Boehler        return $this->cachedValues['calid'][$id];
407185e2535SAndreas Boehler
40851f4febbSAndreas Boehler      $query = "SELECT calid FROM pagetocalendarmapping WHERE page = ?";
40951f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $id);
410a1a3b679SAndreas Boehler      $row = $this->sqlite->res2row($res);
411a1a3b679SAndreas Boehler      if(isset($row['calid']))
412185e2535SAndreas Boehler      {
413185e2535SAndreas Boehler        $calid = $row['calid'];
414185e2535SAndreas Boehler        $this->cachedValues['calid'] = $calid;
415185e2535SAndreas Boehler        return $calid;
416185e2535SAndreas Boehler      }
417a1a3b679SAndreas Boehler      return false;
418a1a3b679SAndreas Boehler  }
419a1a3b679SAndreas Boehler
420cb71a62aSAndreas Boehler  /**
421cb71a62aSAndreas Boehler   * Retrieve the complete calendar id to page mapping.
422cb71a62aSAndreas Boehler   * This is necessary to be able to retrieve a list of
423cb71a62aSAndreas Boehler   * calendars for a given user and check the access rights.
424cb71a62aSAndreas Boehler   *
425cb71a62aSAndreas Boehler   * @return array The mapping array
426cb71a62aSAndreas Boehler   */
427a1a3b679SAndreas Boehler  public function getCalendarIdToPageMapping()
428a1a3b679SAndreas Boehler  {
429a1a3b679SAndreas Boehler      $query = "SELECT calid, page FROM pagetocalendarmapping";
430a1a3b679SAndreas Boehler      $res = $this->sqlite->query($query);
431a1a3b679SAndreas Boehler      $arr = $this->sqlite->res2arr($res);
432a1a3b679SAndreas Boehler      return $arr;
433a1a3b679SAndreas Boehler  }
434a1a3b679SAndreas Boehler
435cb71a62aSAndreas Boehler  /**
436cb71a62aSAndreas Boehler   * Retrieve all calendar IDs a given user has access to.
437cb71a62aSAndreas Boehler   * The user is specified by the principalUri, so the
438cb71a62aSAndreas Boehler   * user name is actually split from the URI component.
439cb71a62aSAndreas Boehler   *
440cb71a62aSAndreas Boehler   * Access rights are checked against DokuWiki's ACL
441cb71a62aSAndreas Boehler   * and applied accordingly.
442cb71a62aSAndreas Boehler   *
443cb71a62aSAndreas Boehler   * @param string $principalUri The principal URI to work on
444cb71a62aSAndreas Boehler   *
445cb71a62aSAndreas Boehler   * @return array An associative array of calendar IDs
446cb71a62aSAndreas Boehler   */
447a1a3b679SAndreas Boehler  public function getCalendarIdsForUser($principalUri)
448a1a3b679SAndreas Boehler  {
44934a47953SAndreas Boehler      global $auth;
450a1a3b679SAndreas Boehler      $user = explode('/', $principalUri);
451a1a3b679SAndreas Boehler      $user = end($user);
452a1a3b679SAndreas Boehler      $mapping = $this->getCalendarIdToPageMapping();
453a1a3b679SAndreas Boehler      $calids = array();
45434a47953SAndreas Boehler      $ud = $auth->getUserData($user);
45534a47953SAndreas Boehler      $groups = $ud['grps'];
456a1a3b679SAndreas Boehler      foreach($mapping as $row)
457a1a3b679SAndreas Boehler      {
458a1a3b679SAndreas Boehler          $id = $row['calid'];
459a1a3b679SAndreas Boehler          $page = $row['page'];
46034a47953SAndreas Boehler          $acl = auth_aclcheck($page, $user, $groups);
461a1a3b679SAndreas Boehler          if($acl >= AUTH_READ)
462a1a3b679SAndreas Boehler          {
463a1a3b679SAndreas Boehler              $write = $acl > AUTH_READ;
464a1a3b679SAndreas Boehler              $calids[$id] = array('readonly' => !$write);
465a1a3b679SAndreas Boehler          }
466a1a3b679SAndreas Boehler      }
467a1a3b679SAndreas Boehler      return $calids;
468a1a3b679SAndreas Boehler  }
469a1a3b679SAndreas Boehler
470cb71a62aSAndreas Boehler  /**
471cb71a62aSAndreas Boehler   * Create a new calendar for a given page ID and set name and description
472cb71a62aSAndreas Boehler   * accordingly. Also update the pagetocalendarmapping table on success.
473cb71a62aSAndreas Boehler   *
474cb71a62aSAndreas Boehler   * @param string $name The calendar's name
475cb71a62aSAndreas Boehler   * @param string $description The calendar's description
476cb71a62aSAndreas Boehler   * @param string $id (optional) The page ID to work on
477cb71a62aSAndreas Boehler   * @param string $userid (optional) The user ID that created the calendar
478cb71a62aSAndreas Boehler   *
479cb71a62aSAndreas Boehler   * @return boolean True on success, otherwise false
480cb71a62aSAndreas Boehler   */
481a1a3b679SAndreas Boehler  public function createCalendarForPage($name, $description, $id = null, $userid = null)
482a1a3b679SAndreas Boehler  {
483a1a3b679SAndreas Boehler      if(is_null($id))
484a1a3b679SAndreas Boehler      {
485a1a3b679SAndreas Boehler          global $ID;
486a1a3b679SAndreas Boehler          $id = $ID;
487a1a3b679SAndreas Boehler      }
488a1a3b679SAndreas Boehler      if(is_null($userid))
48934a47953SAndreas Boehler      {
49034a47953SAndreas Boehler        if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
49134a47953SAndreas Boehler        {
492a1a3b679SAndreas Boehler          $userid = $_SERVER['REMOTE_USER'];
49334a47953SAndreas Boehler        }
49434a47953SAndreas Boehler        else
49534a47953SAndreas Boehler        {
49634a47953SAndreas Boehler          $userid = uniqid('davcal-');
49734a47953SAndreas Boehler        }
49834a47953SAndreas Boehler      }
499a1a3b679SAndreas Boehler      $values = array('principals/'.$userid,
500a1a3b679SAndreas Boehler                      $name,
501a1a3b679SAndreas Boehler                      str_replace(array('/', ' ', ':'), '_', $id),
502a1a3b679SAndreas Boehler                      $description,
503a1a3b679SAndreas Boehler                      'VEVENT,VTODO',
50455a741c0SAndreas Boehler                      0,
50555a741c0SAndreas Boehler                      1);
50651f4febbSAndreas Boehler      $query = "INSERT INTO calendars (principaluri, displayname, uri, description, components, transparent, synctoken) ".
50751f4febbSAndreas Boehler               "VALUES (?, ?, ?, ?, ?, ?, ?)";
50851f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3], $values[4], $values[5], $values[6]);
50955a741c0SAndreas Boehler      if($res === false)
51055a741c0SAndreas Boehler        return false;
511cb71a62aSAndreas Boehler
512cb71a62aSAndreas Boehler      // Get the new calendar ID
51351f4febbSAndreas Boehler      $query = "SELECT id FROM calendars WHERE principaluri = ? AND displayname = ? AND ".
51451f4febbSAndreas Boehler               "uri = ? AND description = ?";
51551f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $values[0], $values[1], $values[2], $values[3]);
516a1a3b679SAndreas Boehler      $row = $this->sqlite->res2row($res);
517cb71a62aSAndreas Boehler
518cb71a62aSAndreas Boehler      // Update the pagetocalendarmapping table with the new calendar ID
519a1a3b679SAndreas Boehler      if(isset($row['id']))
520a1a3b679SAndreas Boehler      {
52151f4febbSAndreas Boehler          $query = "INSERT INTO pagetocalendarmapping (page, calid) VALUES (?, ?)";
52251f4febbSAndreas Boehler          $res = $this->sqlite->query($query, $id, $row['id']);
52355a741c0SAndreas Boehler          return ($res !== false);
524a1a3b679SAndreas Boehler      }
525a1a3b679SAndreas Boehler
526a1a3b679SAndreas Boehler      return false;
527a1a3b679SAndreas Boehler  }
528a1a3b679SAndreas Boehler
529cb71a62aSAndreas Boehler  /**
530cb71a62aSAndreas Boehler   * Add a new iCal entry for a given page, i.e. a given calendar.
531cb71a62aSAndreas Boehler   *
532cb71a62aSAndreas Boehler   * The parameter array needs to contain
533cb71a62aSAndreas Boehler   *   detectedtz       => The timezone as detected by the browser
53482a48dfbSAndreas Boehler   *   currenttz        => The timezone in use by the calendar
535cb71a62aSAndreas Boehler   *   eventfrom        => The event's start date
536cb71a62aSAndreas Boehler   *   eventfromtime    => The event's start time
537cb71a62aSAndreas Boehler   *   eventto          => The event's end date
538cb71a62aSAndreas Boehler   *   eventtotime      => The event's end time
539cb71a62aSAndreas Boehler   *   eventname        => The event's name
540cb71a62aSAndreas Boehler   *   eventdescription => The event's description
541cb71a62aSAndreas Boehler   *
542cb71a62aSAndreas Boehler   * @param string $id The page ID to work on
543cb71a62aSAndreas Boehler   * @param string $user The user who created the calendar
544cb71a62aSAndreas Boehler   * @param string $params A parameter array with values to create
545cb71a62aSAndreas Boehler   *
546cb71a62aSAndreas Boehler   * @return boolean True on success, otherwise false
547cb71a62aSAndreas Boehler   */
548a1a3b679SAndreas Boehler  public function addCalendarEntryToCalendarForPage($id, $user, $params)
549a1a3b679SAndreas Boehler  {
55082a48dfbSAndreas Boehler      if($params['currenttz'] !== '' && $params['currenttz'] !== 'local')
55182a48dfbSAndreas Boehler          $timezone = new \DateTimeZone($params['currenttz']);
55282a48dfbSAndreas Boehler      elseif($params['currenttz'] === 'local')
553a25c89eaSAndreas Boehler          $timezone = new \DateTimeZone($params['detectedtz']);
554bd883736SAndreas Boehler      else
555bd883736SAndreas Boehler          $timezone = new \DateTimeZone('UTC');
556cb71a62aSAndreas Boehler
557cb71a62aSAndreas Boehler      // Retrieve dates from settings
558b269830cSAndreas Boehler      $startDate = explode('-', $params['eventfrom']);
559b269830cSAndreas Boehler      $startTime = explode(':', $params['eventfromtime']);
560b269830cSAndreas Boehler      $endDate = explode('-', $params['eventto']);
561b269830cSAndreas Boehler      $endTime = explode(':', $params['eventtotime']);
562cb71a62aSAndreas Boehler
563cb71a62aSAndreas Boehler      // Load SabreDAV
5649bef4ad8SAndreas Boehler      require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php');
565a1a3b679SAndreas Boehler      $vcalendar = new \Sabre\VObject\Component\VCalendar();
566cb71a62aSAndreas Boehler
567cb71a62aSAndreas Boehler      // Add VCalendar, UID and Event Name
568a1a3b679SAndreas Boehler      $event = $vcalendar->add('VEVENT');
569b269830cSAndreas Boehler      $uuid = \Sabre\VObject\UUIDUtil::getUUID();
570b269830cSAndreas Boehler      $event->add('UID', $uuid);
571a1a3b679SAndreas Boehler      $event->summary = $params['eventname'];
572cb71a62aSAndreas Boehler
573cb71a62aSAndreas Boehler      // Add a description if requested
5740eebc909SAndreas Boehler      $description = $params['eventdescription'];
5750eebc909SAndreas Boehler      if($description !== '')
5760eebc909SAndreas Boehler        $event->add('DESCRIPTION', $description);
577cb71a62aSAndreas Boehler
5784ecb526cSAndreas Boehler      // Add attachments
5794ecb526cSAndreas Boehler      $attachments = $params['attachments'];
58082a48dfbSAndreas Boehler      if(!is_null($attachments))
5814ecb526cSAndreas Boehler        foreach($attachments as $attachment)
5824ecb526cSAndreas Boehler          $event->add('ATTACH', $attachment);
5834ecb526cSAndreas Boehler
584cb71a62aSAndreas Boehler      // Create a timestamp for last modified, created and dtstamp values in UTC
585b269830cSAndreas Boehler      $dtStamp = new \DateTime(null, new \DateTimeZone('UTC'));
586b269830cSAndreas Boehler      $event->add('DTSTAMP', $dtStamp);
587b269830cSAndreas Boehler      $event->add('CREATED', $dtStamp);
588b269830cSAndreas Boehler      $event->add('LAST-MODIFIED', $dtStamp);
589cb71a62aSAndreas Boehler
590cb71a62aSAndreas Boehler      // Adjust the start date, based on the given timezone information
591b269830cSAndreas Boehler      $dtStart = new \DateTime();
592a25c89eaSAndreas Boehler      $dtStart->setTimezone($timezone);
593b269830cSAndreas Boehler      $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2]));
594cb71a62aSAndreas Boehler
595cb71a62aSAndreas Boehler      // Only add the time values if it's not an allday event
596b269830cSAndreas Boehler      if($params['allday'] != '1')
597b269830cSAndreas Boehler        $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0);
598cb71a62aSAndreas Boehler
599cb71a62aSAndreas Boehler      // Adjust the end date, based on the given timezone information
600b269830cSAndreas Boehler      $dtEnd = new \DateTime();
601a25c89eaSAndreas Boehler      $dtEnd->setTimezone($timezone);
602b269830cSAndreas Boehler      $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2]));
603cb71a62aSAndreas Boehler
604cb71a62aSAndreas Boehler      // Only add the time values if it's not an allday event
605b269830cSAndreas Boehler      if($params['allday'] != '1')
606b269830cSAndreas Boehler        $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0);
607cb71a62aSAndreas Boehler
608b269830cSAndreas Boehler      // According to the VCal spec, we need to add a whole day here
609b269830cSAndreas Boehler      if($params['allday'] == '1')
610b269830cSAndreas Boehler          $dtEnd->add(new \DateInterval('P1D'));
611cb71a62aSAndreas Boehler
612cb71a62aSAndreas Boehler      // Really add Start and End events
613b269830cSAndreas Boehler      $dtStartEv = $event->add('DTSTART', $dtStart);
614b269830cSAndreas Boehler      $dtEndEv = $event->add('DTEND', $dtEnd);
615cb71a62aSAndreas Boehler
616cb71a62aSAndreas Boehler      // Adjust the DATE format for allday events
617b269830cSAndreas Boehler      if($params['allday'] == '1')
618b269830cSAndreas Boehler      {
619b269830cSAndreas Boehler          $dtStartEv['VALUE'] = 'DATE';
620b269830cSAndreas Boehler          $dtEndEv['VALUE'] = 'DATE';
621b269830cSAndreas Boehler      }
622cb71a62aSAndreas Boehler
623*809cb0faSAndreas Boehler      $eventStr = $vcalendar->serialize();
624*809cb0faSAndreas Boehler
625*809cb0faSAndreas Boehler      if(strpos($id, 'webdav://') === 0)
626*809cb0faSAndreas Boehler      {
627*809cb0faSAndreas Boehler          $wdc =& plugin_load('helper', 'webdavclient');
628*809cb0faSAndreas Boehler          if(is_null($wdc))
629*809cb0faSAndreas Boehler            return false;
630*809cb0faSAndreas Boehler          $connectionId = str_replace('webdav://', '', $id);
631*809cb0faSAndreas Boehler          return $wdc->addCalendarEntry($connectionId, $eventStr);
632*809cb0faSAndreas Boehler      }
633*809cb0faSAndreas Boehler      else
634*809cb0faSAndreas Boehler      {
635cb71a62aSAndreas Boehler          // Actually add the values to the database
636a1a3b679SAndreas Boehler          $calid = $this->getCalendarIdForPage($id);
637a1a3b679SAndreas Boehler          $uri = uniqid('dokuwiki-').'.ics';
638a1a3b679SAndreas Boehler          $now = new DateTime();
639a1a3b679SAndreas Boehler
64051f4febbSAndreas Boehler          $query = "INSERT INTO calendarobjects (calendarid, uri, calendardata, lastmodified, componenttype, firstoccurence, lastoccurence, size, etag, uid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
64151f4febbSAndreas Boehler          $res = $this->sqlite->query($query, $calid, $uri, $eventStr, $now->getTimestamp(), 'VEVENT',
64251f4febbSAndreas Boehler                                      $event->DTSTART->getDateTime()->getTimeStamp(), $event->DTEND->getDateTime()->getTimeStamp(),
64351f4febbSAndreas Boehler                                      strlen($eventStr), md5($eventStr), $uuid);
644cb71a62aSAndreas Boehler
645cb71a62aSAndreas Boehler          // If successfully, update the sync token database
64655a741c0SAndreas Boehler          if($res !== false)
64755a741c0SAndreas Boehler          {
64855a741c0SAndreas Boehler              $this->updateSyncTokenLog($calid, $uri, 'added');
649a1a3b679SAndreas Boehler              return true;
650a1a3b679SAndreas Boehler          }
651*809cb0faSAndreas Boehler      }
65255a741c0SAndreas Boehler      return false;
65355a741c0SAndreas Boehler  }
654a1a3b679SAndreas Boehler
655cb71a62aSAndreas Boehler  /**
656cb71a62aSAndreas Boehler   * Retrieve the calendar settings of a given calendar id
657cb71a62aSAndreas Boehler   *
658cb71a62aSAndreas Boehler   * @param string $calid The calendar ID
659cb71a62aSAndreas Boehler   *
660cb71a62aSAndreas Boehler   * @return array The calendar settings array
661cb71a62aSAndreas Boehler   */
662b269830cSAndreas Boehler  public function getCalendarSettings($calid)
663b269830cSAndreas Boehler  {
66451f4febbSAndreas Boehler      $query = "SELECT principaluri, calendarcolor, displayname, uri, description, components, transparent, synctoken FROM calendars WHERE id= ? ";
66551f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $calid);
666b269830cSAndreas Boehler      $row = $this->sqlite->res2row($res);
667b269830cSAndreas Boehler      return $row;
668b269830cSAndreas Boehler  }
669b269830cSAndreas Boehler
670cb71a62aSAndreas Boehler  /**
671cb71a62aSAndreas Boehler   * Retrieve all events that are within a given date range,
672cb71a62aSAndreas Boehler   * based on the timezone setting.
673cb71a62aSAndreas Boehler   *
674cb71a62aSAndreas Boehler   * There is also support for retrieving recurring events,
675cb71a62aSAndreas Boehler   * using Sabre's VObject Iterator. Recurring events are represented
676cb71a62aSAndreas Boehler   * as individual calendar entries with the same UID.
677cb71a62aSAndreas Boehler   *
678cb71a62aSAndreas Boehler   * @param string $id The page ID to work with
679cb71a62aSAndreas Boehler   * @param string $user The user ID to work with
680cb71a62aSAndreas Boehler   * @param string $startDate The start date as a string
681cb71a62aSAndreas Boehler   * @param string $endDate The end date as a string
6824a2bf5eeSAndreas Boehler   * @param string $color (optional) The calendar's color
683cb71a62aSAndreas Boehler   *
684cb71a62aSAndreas Boehler   * @return array An array containing the calendar entries.
685cb71a62aSAndreas Boehler   */
6864a2bf5eeSAndreas Boehler  public function getEventsWithinDateRange($id, $user, $startDate, $endDate, $timezone, $color = null)
687a1a3b679SAndreas Boehler  {
68882a48dfbSAndreas Boehler      if($timezone !== '' && $timezone !== 'local')
68982a48dfbSAndreas Boehler          $timezone = new \DateTimeZone($timezone);
690bd883736SAndreas Boehler      else
691bd883736SAndreas Boehler          $timezone = new \DateTimeZone('UTC');
692a1a3b679SAndreas Boehler      $data = array();
693cb71a62aSAndreas Boehler
694a469597cSAndreas Boehler      $query = "SELECT calendardata, componenttype, uid FROM calendarobjects WHERE calendarid = ?";
695a469597cSAndreas Boehler      $startTs = null;
696a469597cSAndreas Boehler      $endTs = null;
697a469597cSAndreas Boehler      if($startDate !== null)
698a469597cSAndreas Boehler      {
699a1a3b679SAndreas Boehler        $startTs = new \DateTime($startDate);
700a469597cSAndreas Boehler        $query .= " AND lastoccurence > ".$this->sqlite->quote_string($startTs->getTimestamp());
701a469597cSAndreas Boehler      }
702a469597cSAndreas Boehler      if($endDate !== null)
703a469597cSAndreas Boehler      {
704a1a3b679SAndreas Boehler        $endTs = new \DateTime($endDate);
705a469597cSAndreas Boehler        $query .= " AND firstoccurence < ".$this->sqlite->quote_string($endTs->getTimestamp());
706a469597cSAndreas Boehler      }
707cb71a62aSAndreas Boehler
7080b805092SAndreas Boehler      // Load SabreDAV
7090b805092SAndreas Boehler      require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php');
7100b805092SAndreas Boehler
7110b805092SAndreas Boehler      if(strpos($id, 'webdav://') === 0)
7120b805092SAndreas Boehler      {
7130b805092SAndreas Boehler          $wdc =& plugin_load('helper', 'webdavclient');
7140b805092SAndreas Boehler          if(is_null($wdc))
7150b805092SAndreas Boehler            return $data;
7160b805092SAndreas Boehler          $connectionId = str_replace('webdav://', '', $id);
7170b805092SAndreas Boehler          $arr = $wdc->getCalendarEntries($connectionId, $startDate, $endDate);
7180b805092SAndreas Boehler      }
7190b805092SAndreas Boehler      else
7200b805092SAndreas Boehler      {
7210b805092SAndreas Boehler          $calid = $this->getCalendarIdForPage($id);
7220b805092SAndreas Boehler          if(is_null($color))
7230b805092SAndreas Boehler            $color = $this->getCalendarColorForCalendar($calid);
7240b805092SAndreas Boehler
725cb71a62aSAndreas Boehler          // Retrieve matching calendar objects
726a469597cSAndreas Boehler          $res = $this->sqlite->query($query, $calid);
727a1a3b679SAndreas Boehler          $arr = $this->sqlite->res2arr($res);
7280b805092SAndreas Boehler      }
729cb71a62aSAndreas Boehler
730cb71a62aSAndreas Boehler      // Parse individual calendar entries
731a1a3b679SAndreas Boehler      foreach($arr as $row)
732a1a3b679SAndreas Boehler      {
733a1a3b679SAndreas Boehler          if(isset($row['calendardata']))
734a1a3b679SAndreas Boehler          {
735b269830cSAndreas Boehler              $entry = array();
736a1a3b679SAndreas Boehler              $vcal = \Sabre\VObject\Reader::read($row['calendardata']);
737ebc4eb57SAndreas Boehler              $recurrence = $vcal->VEVENT->RRULE;
738cb71a62aSAndreas Boehler              // If it is a recurring event, pass it through Sabre's EventIterator
739ebc4eb57SAndreas Boehler              if($recurrence != null)
740ebc4eb57SAndreas Boehler              {
741ebc4eb57SAndreas Boehler                  $rEvents = new \Sabre\VObject\Recur\EventIterator(array($vcal->VEVENT));
742ebc4eb57SAndreas Boehler                  $rEvents->rewind();
743e9b7d302SAndreas Boehler                  while($rEvents->valid())
744ebc4eb57SAndreas Boehler                  {
745ebc4eb57SAndreas Boehler                      $event = $rEvents->getEventObject();
746cb71a62aSAndreas Boehler                      // If we are after the given time range, exit
747a469597cSAndreas Boehler                      if(($endTs !== null) && ($rEvents->getDtStart()->getTimestamp() > $endTs->getTimestamp()))
748e9b7d302SAndreas Boehler                          break;
749cb71a62aSAndreas Boehler
750cb71a62aSAndreas Boehler                      // If we are before the given time range, continue
751a469597cSAndreas Boehler                      if(($startTs != null) && ($rEvents->getDtEnd()->getTimestamp() < $startTs->getTimestamp()))
752ebc4eb57SAndreas Boehler                      {
753ebc4eb57SAndreas Boehler                          $rEvents->next();
754ebc4eb57SAndreas Boehler                          continue;
755ebc4eb57SAndreas Boehler                      }
756cb71a62aSAndreas Boehler
757cb71a62aSAndreas Boehler                      // If we are within the given time range, parse the event
758185e2535SAndreas Boehler                      $data[] = $this->convertIcalDataToEntry($event, $id, $timezone, $row['uid'], $color, true);
759ebc4eb57SAndreas Boehler                      $rEvents->next();
760ebc4eb57SAndreas Boehler                  }
761ebc4eb57SAndreas Boehler              }
762ebc4eb57SAndreas Boehler              else
763185e2535SAndreas Boehler                $data[] = $this->convertIcalDataToEntry($vcal->VEVENT, $id, $timezone, $row['uid'], $color);
764ebc4eb57SAndreas Boehler          }
765ebc4eb57SAndreas Boehler      }
766ebc4eb57SAndreas Boehler      return $data;
767ebc4eb57SAndreas Boehler  }
768ebc4eb57SAndreas Boehler
769cb71a62aSAndreas Boehler  /**
770cb71a62aSAndreas Boehler   * Helper function that parses the iCal data of a VEVENT to a calendar entry.
771cb71a62aSAndreas Boehler   *
772cb71a62aSAndreas Boehler   * @param \Sabre\VObject\VEvent $event The event to parse
773cb71a62aSAndreas Boehler   * @param \DateTimeZone $timezone The timezone object
774cb71a62aSAndreas Boehler   * @param string $uid The entry's UID
7753c86dda8SAndreas Boehler   * @param boolean $recurring (optional) Set to true to define a recurring event
776cb71a62aSAndreas Boehler   *
777cb71a62aSAndreas Boehler   * @return array The parse calendar entry
778cb71a62aSAndreas Boehler   */
779185e2535SAndreas Boehler  private function convertIcalDataToEntry($event, $page, $timezone, $uid, $color, $recurring = false)
780ebc4eb57SAndreas Boehler  {
781ebc4eb57SAndreas Boehler      $entry = array();
782ebc4eb57SAndreas Boehler      $start = $event->DTSTART;
783cb71a62aSAndreas Boehler      // Parse only if the start date/time is present
784b269830cSAndreas Boehler      if($start !== null)
785b269830cSAndreas Boehler      {
786b269830cSAndreas Boehler        $dtStart = $start->getDateTime();
787b269830cSAndreas Boehler        $dtStart->setTimezone($timezone);
788bf0ad2b4SAndreas Boehler
789bf0ad2b4SAndreas Boehler        // moment.js doesn't like times be given even if
790bf0ad2b4SAndreas Boehler        // allDay is set to true
791bf0ad2b4SAndreas Boehler        // This should fix T23
792b269830cSAndreas Boehler        if($start['VALUE'] == 'DATE')
793bf0ad2b4SAndreas Boehler        {
794b269830cSAndreas Boehler          $entry['allDay'] = true;
795bf0ad2b4SAndreas Boehler          $entry['start'] = $dtStart->format("Y-m-d");
796bf0ad2b4SAndreas Boehler        }
797b269830cSAndreas Boehler        else
798bf0ad2b4SAndreas Boehler        {
799b269830cSAndreas Boehler          $entry['allDay'] = false;
800bf0ad2b4SAndreas Boehler          $entry['start'] = $dtStart->format(\DateTime::ATOM);
801bf0ad2b4SAndreas Boehler        }
802b269830cSAndreas Boehler      }
803ebc4eb57SAndreas Boehler      $end = $event->DTEND;
804bf0ad2b4SAndreas Boehler      // Parse only if the end date/time is present
805b269830cSAndreas Boehler      if($end !== null)
806b269830cSAndreas Boehler      {
807b269830cSAndreas Boehler        $dtEnd = $end->getDateTime();
808b269830cSAndreas Boehler        $dtEnd->setTimezone($timezone);
809bf0ad2b4SAndreas Boehler        if($end['VALUE'] == 'DATE')
810bf0ad2b4SAndreas Boehler          $entry['end'] = $dtEnd->format("Y-m-d");
811bf0ad2b4SAndreas Boehler        else
812b269830cSAndreas Boehler          $entry['end'] = $dtEnd->format(\DateTime::ATOM);
813b269830cSAndreas Boehler      }
814ebc4eb57SAndreas Boehler      $description = $event->DESCRIPTION;
8150eebc909SAndreas Boehler      if($description !== null)
8160eebc909SAndreas Boehler        $entry['description'] = (string)$description;
8170eebc909SAndreas Boehler      else
8180eebc909SAndreas Boehler        $entry['description'] = '';
8194ecb526cSAndreas Boehler      $attachments = $event->ATTACH;
8204ecb526cSAndreas Boehler      if($attachments !== null)
8214ecb526cSAndreas Boehler      {
8224ecb526cSAndreas Boehler        $entry['attachments'] = array();
8234ecb526cSAndreas Boehler        foreach($attachments as $attachment)
8244ecb526cSAndreas Boehler          $entry['attachments'][] = (string)$attachment;
8254ecb526cSAndreas Boehler      }
826ebc4eb57SAndreas Boehler      $entry['title'] = (string)$event->summary;
827ebc4eb57SAndreas Boehler      $entry['id'] = $uid;
828185e2535SAndreas Boehler      $entry['page'] = $page;
829185e2535SAndreas Boehler      $entry['color'] = $color;
8303c86dda8SAndreas Boehler      $entry['recurring'] = $recurring;
831185e2535SAndreas Boehler
832ebc4eb57SAndreas Boehler      return $entry;
833a1a3b679SAndreas Boehler  }
834a1a3b679SAndreas Boehler
835cb71a62aSAndreas Boehler  /**
836cb71a62aSAndreas Boehler   * Retrieve an event by its UID
837cb71a62aSAndreas Boehler   *
838cb71a62aSAndreas Boehler   * @param string $uid The event's UID
839cb71a62aSAndreas Boehler   *
840cb71a62aSAndreas Boehler   * @return mixed The table row with the given event
841cb71a62aSAndreas Boehler   */
842a1a3b679SAndreas Boehler  public function getEventWithUid($uid)
843a1a3b679SAndreas Boehler  {
84451f4febbSAndreas Boehler      $query = "SELECT calendardata, calendarid, componenttype, uri FROM calendarobjects WHERE uid = ?";
84551f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $uid);
846a1a3b679SAndreas Boehler      $row = $this->sqlite->res2row($res);
847a1a3b679SAndreas Boehler      return $row;
848a1a3b679SAndreas Boehler  }
849a1a3b679SAndreas Boehler
850cb71a62aSAndreas Boehler  /**
851cb71a62aSAndreas Boehler   * Retrieve all calendar events for a given calendar ID
852cb71a62aSAndreas Boehler   *
853cb71a62aSAndreas Boehler   * @param string $calid The calendar's ID
854cb71a62aSAndreas Boehler   *
855cb71a62aSAndreas Boehler   * @return array An array containing all calendar data
856cb71a62aSAndreas Boehler   */
857f69bb449SAndreas Boehler  public function getAllCalendarEvents($calid)
858f69bb449SAndreas Boehler  {
8597e0b8590SAndreas Boehler      $query = "SELECT calendardata, uid, componenttype, uri FROM calendarobjects WHERE calendarid = ?";
86051f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $calid);
861f69bb449SAndreas Boehler      $arr = $this->sqlite->res2arr($res);
862f69bb449SAndreas Boehler      return $arr;
863f69bb449SAndreas Boehler  }
864f69bb449SAndreas Boehler
865cb71a62aSAndreas Boehler  /**
866cb71a62aSAndreas Boehler   * Edit a calendar entry for a page, given by its parameters.
867cb71a62aSAndreas Boehler   * The params array has the same format as @see addCalendarEntryForPage
868cb71a62aSAndreas Boehler   *
869cb71a62aSAndreas Boehler   * @param string $id The page's ID to work on
870cb71a62aSAndreas Boehler   * @param string $user The user's ID to work on
871cb71a62aSAndreas Boehler   * @param array $params The parameter array for the edited calendar event
872cb71a62aSAndreas Boehler   *
873cb71a62aSAndreas Boehler   * @return boolean True on success, otherwise false
874cb71a62aSAndreas Boehler   */
875a1a3b679SAndreas Boehler  public function editCalendarEntryForPage($id, $user, $params)
876a1a3b679SAndreas Boehler  {
87782a48dfbSAndreas Boehler      if($params['currenttz'] !== '' && $params['currenttz'] !== 'local')
87882a48dfbSAndreas Boehler          $timezone = new \DateTimeZone($params['currenttz']);
87982a48dfbSAndreas Boehler      elseif($params['currenttz'] === 'local')
880a25c89eaSAndreas Boehler          $timezone = new \DateTimeZone($params['detectedtz']);
881bd883736SAndreas Boehler      else
882bd883736SAndreas Boehler          $timezone = new \DateTimeZone('UTC');
883cb71a62aSAndreas Boehler
884cb71a62aSAndreas Boehler      // Parse dates
885b269830cSAndreas Boehler      $startDate = explode('-', $params['eventfrom']);
886b269830cSAndreas Boehler      $startTime = explode(':', $params['eventfromtime']);
887b269830cSAndreas Boehler      $endDate = explode('-', $params['eventto']);
888b269830cSAndreas Boehler      $endTime = explode(':', $params['eventtotime']);
889cb71a62aSAndreas Boehler
890cb71a62aSAndreas Boehler      // Retrieve the existing event based on the UID
89155a741c0SAndreas Boehler      $uid = $params['uid'];
892*809cb0faSAndreas Boehler
893*809cb0faSAndreas Boehler      if(strpos($id, 'webdav://') === 0)
894*809cb0faSAndreas Boehler      {
895*809cb0faSAndreas Boehler        $wdc =& plugin_load('helper', 'webdavclient');
896*809cb0faSAndreas Boehler        if(is_null($wdc))
897*809cb0faSAndreas Boehler          return false;
898*809cb0faSAndreas Boehler        $event = $wdc->getCalendarEntryByUid($uid);
899*809cb0faSAndreas Boehler      }
900*809cb0faSAndreas Boehler      else
901*809cb0faSAndreas Boehler      {
90255a741c0SAndreas Boehler        $event = $this->getEventWithUid($uid);
903*809cb0faSAndreas Boehler      }
904cb71a62aSAndreas Boehler
905cb71a62aSAndreas Boehler      // Load SabreDAV
9069bef4ad8SAndreas Boehler      require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php');
907a1a3b679SAndreas Boehler      if(!isset($event['calendardata']))
908a1a3b679SAndreas Boehler        return false;
90955a741c0SAndreas Boehler      $uri = $event['uri'];
91055a741c0SAndreas Boehler      $calid = $event['calendarid'];
911cb71a62aSAndreas Boehler
912cb71a62aSAndreas Boehler      // Parse the existing event
913a1a3b679SAndreas Boehler      $vcal = \Sabre\VObject\Reader::read($event['calendardata']);
914b269830cSAndreas Boehler      $vevent = $vcal->VEVENT;
915cb71a62aSAndreas Boehler
916cb71a62aSAndreas Boehler      // Set the new event values
917b269830cSAndreas Boehler      $vevent->summary = $params['eventname'];
918b269830cSAndreas Boehler      $dtStamp = new \DateTime(null, new \DateTimeZone('UTC'));
9190eebc909SAndreas Boehler      $description = $params['eventdescription'];
920cb71a62aSAndreas Boehler
921cb71a62aSAndreas Boehler      // Remove existing timestamps to overwrite them
9220eebc909SAndreas Boehler      $vevent->remove('DESCRIPTION');
923b269830cSAndreas Boehler      $vevent->remove('DTSTAMP');
924b269830cSAndreas Boehler      $vevent->remove('LAST-MODIFIED');
9254ecb526cSAndreas Boehler      $vevent->remove('ATTACH');
926cb71a62aSAndreas Boehler
927cb71a62aSAndreas Boehler      // Add new time stamps and description
928b269830cSAndreas Boehler      $vevent->add('DTSTAMP', $dtStamp);
929b269830cSAndreas Boehler      $vevent->add('LAST-MODIFIED', $dtStamp);
9300eebc909SAndreas Boehler      if($description !== '')
9310eebc909SAndreas Boehler        $vevent->add('DESCRIPTION', $description);
932cb71a62aSAndreas Boehler
9334ecb526cSAndreas Boehler      // Add attachments
9344ecb526cSAndreas Boehler      $attachments = $params['attachments'];
93582a48dfbSAndreas Boehler      if(!is_null($attachments))
9364ecb526cSAndreas Boehler        foreach($attachments as $attachment)
9374ecb526cSAndreas Boehler          $vevent->add('ATTACH', $attachment);
9384ecb526cSAndreas Boehler
939cb71a62aSAndreas Boehler      // Setup DTSTART
940b269830cSAndreas Boehler      $dtStart = new \DateTime();
941a25c89eaSAndreas Boehler      $dtStart->setTimezone($timezone);
942b269830cSAndreas Boehler      $dtStart->setDate(intval($startDate[0]), intval($startDate[1]), intval($startDate[2]));
943b269830cSAndreas Boehler      if($params['allday'] != '1')
944b269830cSAndreas Boehler        $dtStart->setTime(intval($startTime[0]), intval($startTime[1]), 0);
945cb71a62aSAndreas Boehler
9464ecb526cSAndreas Boehler      // Setup DTEND
947b269830cSAndreas Boehler      $dtEnd = new \DateTime();
948a25c89eaSAndreas Boehler      $dtEnd->setTimezone($timezone);
949b269830cSAndreas Boehler      $dtEnd->setDate(intval($endDate[0]), intval($endDate[1]), intval($endDate[2]));
950b269830cSAndreas Boehler      if($params['allday'] != '1')
951b269830cSAndreas Boehler        $dtEnd->setTime(intval($endTime[0]), intval($endTime[1]), 0);
952cb71a62aSAndreas Boehler
953b269830cSAndreas Boehler      // According to the VCal spec, we need to add a whole day here
954b269830cSAndreas Boehler      if($params['allday'] == '1')
955b269830cSAndreas Boehler          $dtEnd->add(new \DateInterval('P1D'));
956b269830cSAndreas Boehler      $vevent->remove('DTSTART');
957b269830cSAndreas Boehler      $vevent->remove('DTEND');
958b269830cSAndreas Boehler      $dtStartEv = $vevent->add('DTSTART', $dtStart);
959b269830cSAndreas Boehler      $dtEndEv = $vevent->add('DTEND', $dtEnd);
960cb71a62aSAndreas Boehler
961cb71a62aSAndreas Boehler      // Remove the time for allday events
962b269830cSAndreas Boehler      if($params['allday'] == '1')
963b269830cSAndreas Boehler      {
964b269830cSAndreas Boehler          $dtStartEv['VALUE'] = 'DATE';
965b269830cSAndreas Boehler          $dtEndEv['VALUE'] = 'DATE';
966b269830cSAndreas Boehler      }
967a1a3b679SAndreas Boehler      $eventStr = $vcal->serialize();
968*809cb0faSAndreas Boehler      if(strpos($id, 'webdav://') === 0)
969*809cb0faSAndreas Boehler      {
970*809cb0faSAndreas Boehler          $connectionId = str_replace('webdav://', '', $id);
971*809cb0faSAndreas Boehler          return $wdc->editCalendarEntry($connectionId, $uid, $eventStr);
972*809cb0faSAndreas Boehler      }
973*809cb0faSAndreas Boehler      else
974*809cb0faSAndreas Boehler      {
975*809cb0faSAndreas Boehler          $now = new DateTime();
976cb71a62aSAndreas Boehler          // Actually write to the database
97751f4febbSAndreas Boehler          $query = "UPDATE calendarobjects SET calendardata = ?, lastmodified = ?, ".
97851f4febbSAndreas Boehler                   "firstoccurence = ?, lastoccurence = ?, size = ?, etag = ? WHERE uid = ?";
97951f4febbSAndreas Boehler          $res = $this->sqlite->query($query, $eventStr, $now->getTimestamp(), $dtStart->getTimestamp(),
98051f4febbSAndreas Boehler                                      $dtEnd->getTimestamp(), strlen($eventStr), md5($eventStr), $uid);
98155a741c0SAndreas Boehler          if($res !== false)
98255a741c0SAndreas Boehler          {
98355a741c0SAndreas Boehler              $this->updateSyncTokenLog($calid, $uri, 'modified');
984a1a3b679SAndreas Boehler              return true;
985a1a3b679SAndreas Boehler          }
986*809cb0faSAndreas Boehler      }
98755a741c0SAndreas Boehler      return false;
98855a741c0SAndreas Boehler  }
989a1a3b679SAndreas Boehler
990cb71a62aSAndreas Boehler  /**
991cb71a62aSAndreas Boehler   * Delete a calendar entry for a given page. Actually, the event is removed
992cb71a62aSAndreas Boehler   * based on the entry's UID, so that page ID is no used.
993cb71a62aSAndreas Boehler   *
994cb71a62aSAndreas Boehler   * @param string $id The page's ID (unused)
995cb71a62aSAndreas Boehler   * @param array $params The parameter array to work with
996cb71a62aSAndreas Boehler   *
997cb71a62aSAndreas Boehler   * @return boolean True
998cb71a62aSAndreas Boehler   */
999a1a3b679SAndreas Boehler  public function deleteCalendarEntryForPage($id, $params)
1000a1a3b679SAndreas Boehler  {
1001a1a3b679SAndreas Boehler      $uid = $params['uid'];
1002*809cb0faSAndreas Boehler      if(strpos($id, 'webdav://') === 0)
1003*809cb0faSAndreas Boehler      {
1004*809cb0faSAndreas Boehler        $wdc =& plugin_load('helper', 'webdavclient');
1005*809cb0faSAndreas Boehler        if(is_null($wdc))
1006*809cb0faSAndreas Boehler          return false;
1007*809cb0faSAndreas Boehler        $connectionId = str_replace('webdav://', '', $id);
1008*809cb0faSAndreas Boehler        $result = $wdc->deleteCalendarEntry($connectionId, $uid);
1009*809cb0faSAndreas Boehler        return $result;
1010*809cb0faSAndreas Boehler      }
101155a741c0SAndreas Boehler      $event = $this->getEventWithUid($uid);
10122c14b82bSAndreas Boehler      $calid = $event['calendarid'];
101355a741c0SAndreas Boehler      $uri = $event['uri'];
101451f4febbSAndreas Boehler      $query = "DELETE FROM calendarobjects WHERE uid = ?";
101551f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $uid);
101655a741c0SAndreas Boehler      if($res !== false)
101755a741c0SAndreas Boehler      {
101855a741c0SAndreas Boehler          $this->updateSyncTokenLog($calid, $uri, 'deleted');
101955a741c0SAndreas Boehler      }
1020a1a3b679SAndreas Boehler      return true;
1021a1a3b679SAndreas Boehler  }
1022a1a3b679SAndreas Boehler
1023cb71a62aSAndreas Boehler  /**
1024cb71a62aSAndreas Boehler   * Retrieve the current sync token for a calendar
1025cb71a62aSAndreas Boehler   *
1026cb71a62aSAndreas Boehler   * @param string $calid The calendar id
1027cb71a62aSAndreas Boehler   *
1028cb71a62aSAndreas Boehler   * @return mixed The synctoken or false
1029cb71a62aSAndreas Boehler   */
103055a741c0SAndreas Boehler  public function getSyncTokenForCalendar($calid)
103155a741c0SAndreas Boehler  {
1032b269830cSAndreas Boehler      $row = $this->getCalendarSettings($calid);
103355a741c0SAndreas Boehler      if(isset($row['synctoken']))
103455a741c0SAndreas Boehler          return $row['synctoken'];
103555a741c0SAndreas Boehler      return false;
103655a741c0SAndreas Boehler  }
103755a741c0SAndreas Boehler
1038cb71a62aSAndreas Boehler  /**
1039cb71a62aSAndreas Boehler   * Helper function to convert the operation name to
1040cb71a62aSAndreas Boehler   * an operation code as stored in the database
1041cb71a62aSAndreas Boehler   *
1042cb71a62aSAndreas Boehler   * @param string $operationName The operation name
1043cb71a62aSAndreas Boehler   *
1044cb71a62aSAndreas Boehler   * @return mixed The operation code or false
1045cb71a62aSAndreas Boehler   */
104655a741c0SAndreas Boehler  public function operationNameToOperation($operationName)
104755a741c0SAndreas Boehler  {
104855a741c0SAndreas Boehler      switch($operationName)
104955a741c0SAndreas Boehler      {
105055a741c0SAndreas Boehler          case 'added':
105155a741c0SAndreas Boehler              return 1;
105255a741c0SAndreas Boehler          break;
105355a741c0SAndreas Boehler          case 'modified':
105455a741c0SAndreas Boehler              return 2;
105555a741c0SAndreas Boehler          break;
105655a741c0SAndreas Boehler          case 'deleted':
105755a741c0SAndreas Boehler              return 3;
105855a741c0SAndreas Boehler          break;
105955a741c0SAndreas Boehler      }
106055a741c0SAndreas Boehler      return false;
106155a741c0SAndreas Boehler  }
106255a741c0SAndreas Boehler
1063cb71a62aSAndreas Boehler  /**
1064cb71a62aSAndreas Boehler   * Update the sync token log based on the calendar id and the
1065cb71a62aSAndreas Boehler   * operation that was performed.
1066cb71a62aSAndreas Boehler   *
1067cb71a62aSAndreas Boehler   * @param string $calid The calendar ID that was modified
1068cb71a62aSAndreas Boehler   * @param string $uri The calendar URI that was modified
1069cb71a62aSAndreas Boehler   * @param string $operation The operation that was performed
1070cb71a62aSAndreas Boehler   *
1071cb71a62aSAndreas Boehler   * @return boolean True on success, otherwise false
1072cb71a62aSAndreas Boehler   */
107355a741c0SAndreas Boehler  private function updateSyncTokenLog($calid, $uri, $operation)
107455a741c0SAndreas Boehler  {
107555a741c0SAndreas Boehler      $currentToken = $this->getSyncTokenForCalendar($calid);
107655a741c0SAndreas Boehler      $operationCode = $this->operationNameToOperation($operation);
107755a741c0SAndreas Boehler      if(($operationCode === false) || ($currentToken === false))
107855a741c0SAndreas Boehler          return false;
107955a741c0SAndreas Boehler      $values = array($uri,
108055a741c0SAndreas Boehler                      $currentToken,
108155a741c0SAndreas Boehler                      $calid,
108255a741c0SAndreas Boehler                      $operationCode
108355a741c0SAndreas Boehler      );
108451f4febbSAndreas Boehler      $query = "INSERT INTO calendarchanges (uri, synctoken, calendarid, operation) VALUES(?, ?, ?, ?)";
108551f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $uri, $currentToken, $calid, $operationCode);
108655a741c0SAndreas Boehler      if($res === false)
108755a741c0SAndreas Boehler        return false;
108855a741c0SAndreas Boehler      $currentToken++;
108951f4febbSAndreas Boehler      $query = "UPDATE calendars SET synctoken = ? WHERE id = ?";
109051f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $currentToken, $calid);
109155a741c0SAndreas Boehler      return ($res !== false);
109255a741c0SAndreas Boehler  }
109355a741c0SAndreas Boehler
1094cb71a62aSAndreas Boehler  /**
1095cb71a62aSAndreas Boehler   * Return the sync URL for a given Page, i.e. a calendar
1096cb71a62aSAndreas Boehler   *
1097cb71a62aSAndreas Boehler   * @param string $id The page's ID
1098cb71a62aSAndreas Boehler   * @param string $user (optional) The user's ID
1099cb71a62aSAndreas Boehler   *
1100cb71a62aSAndreas Boehler   * @return mixed The sync url or false
1101cb71a62aSAndreas Boehler   */
1102b269830cSAndreas Boehler  public function getSyncUrlForPage($id, $user = null)
1103b269830cSAndreas Boehler  {
110434a47953SAndreas Boehler      if(is_null($userid))
110534a47953SAndreas Boehler      {
110634a47953SAndreas Boehler        if(isset($_SERVER['REMOTE_USER']) && !is_null($_SERVER['REMOTE_USER']))
110734a47953SAndreas Boehler        {
110834a47953SAndreas Boehler          $userid = $_SERVER['REMOTE_USER'];
110934a47953SAndreas Boehler        }
111034a47953SAndreas Boehler        else
111134a47953SAndreas Boehler        {
111234a47953SAndreas Boehler          return false;
111334a47953SAndreas Boehler        }
111434a47953SAndreas Boehler      }
1115b269830cSAndreas Boehler
1116b269830cSAndreas Boehler      $calid = $this->getCalendarIdForPage($id);
1117b269830cSAndreas Boehler      if($calid === false)
1118b269830cSAndreas Boehler        return false;
1119b269830cSAndreas Boehler
1120b269830cSAndreas Boehler      $calsettings = $this->getCalendarSettings($calid);
1121b269830cSAndreas Boehler      if(!isset($calsettings['uri']))
1122b269830cSAndreas Boehler        return false;
1123b269830cSAndreas Boehler
1124b269830cSAndreas Boehler      $syncurl = DOKU_URL.'lib/plugins/davcal/calendarserver.php/calendars/'.$user.'/'.$calsettings['uri'];
1125b269830cSAndreas Boehler      return $syncurl;
1126b269830cSAndreas Boehler  }
1127b269830cSAndreas Boehler
1128cb71a62aSAndreas Boehler  /**
1129cb71a62aSAndreas Boehler   * Return the private calendar's URL for a given page
1130cb71a62aSAndreas Boehler   *
1131cb71a62aSAndreas Boehler   * @param string $id the page ID
1132cb71a62aSAndreas Boehler   *
1133cb71a62aSAndreas Boehler   * @return mixed The private URL or false
1134cb71a62aSAndreas Boehler   */
1135f69bb449SAndreas Boehler  public function getPrivateURLForPage($id)
1136f69bb449SAndreas Boehler  {
1137f69bb449SAndreas Boehler      $calid = $this->getCalendarIdForPage($id);
1138f69bb449SAndreas Boehler      if($calid === false)
1139f69bb449SAndreas Boehler        return false;
1140f69bb449SAndreas Boehler
1141f69bb449SAndreas Boehler      return $this->getPrivateURLForCalendar($calid);
1142f69bb449SAndreas Boehler  }
1143f69bb449SAndreas Boehler
1144cb71a62aSAndreas Boehler  /**
1145cb71a62aSAndreas Boehler   * Return the private calendar's URL for a given calendar ID
1146cb71a62aSAndreas Boehler   *
1147cb71a62aSAndreas Boehler   * @param string $calid The calendar's ID
1148cb71a62aSAndreas Boehler   *
1149cb71a62aSAndreas Boehler   * @return mixed The private URL or false
1150cb71a62aSAndreas Boehler   */
1151f69bb449SAndreas Boehler  public function getPrivateURLForCalendar($calid)
1152f69bb449SAndreas Boehler  {
1153185e2535SAndreas Boehler      if(isset($this->cachedValues['privateurl'][$calid]))
1154185e2535SAndreas Boehler        return $this->cachedValues['privateurl'][$calid];
115551f4febbSAndreas Boehler      $query = "SELECT url FROM calendartoprivateurlmapping WHERE calid = ?";
115651f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $calid);
1157f69bb449SAndreas Boehler      $row = $this->sqlite->res2row($res);
1158f69bb449SAndreas Boehler      if(!isset($row['url']))
1159f69bb449SAndreas Boehler      {
1160f69bb449SAndreas Boehler          $url = uniqid("dokuwiki-").".ics";
116151f4febbSAndreas Boehler          $query = "INSERT INTO calendartoprivateurlmapping (url, calid) VALUES(?, ?)";
116251f4febbSAndreas Boehler          $res = $this->sqlite->query($query, $url, $calid);
1163f69bb449SAndreas Boehler          if($res === false)
1164f69bb449SAndreas Boehler            return false;
1165f69bb449SAndreas Boehler      }
1166f69bb449SAndreas Boehler      else
1167f69bb449SAndreas Boehler      {
1168f69bb449SAndreas Boehler          $url = $row['url'];
1169f69bb449SAndreas Boehler      }
1170185e2535SAndreas Boehler
1171185e2535SAndreas Boehler      $url = DOKU_URL.'lib/plugins/davcal/ics.php/'.$url;
1172185e2535SAndreas Boehler      $this->cachedValues['privateurl'][$calid] = $url;
1173185e2535SAndreas Boehler      return $url;
1174f69bb449SAndreas Boehler  }
1175f69bb449SAndreas Boehler
1176cb71a62aSAndreas Boehler  /**
1177cb71a62aSAndreas Boehler   * Retrieve the calendar ID for a given private calendar URL
1178cb71a62aSAndreas Boehler   *
1179cb71a62aSAndreas Boehler   * @param string $url The private URL
1180cb71a62aSAndreas Boehler   *
1181cb71a62aSAndreas Boehler   * @return mixed The calendar ID or false
1182cb71a62aSAndreas Boehler   */
1183f69bb449SAndreas Boehler  public function getCalendarForPrivateURL($url)
1184f69bb449SAndreas Boehler  {
118551f4febbSAndreas Boehler      $query = "SELECT calid FROM calendartoprivateurlmapping WHERE url = ?";
118651f4febbSAndreas Boehler      $res = $this->sqlite->query($query, $url);
1187f69bb449SAndreas Boehler      $row = $this->sqlite->res2row($res);
1188f69bb449SAndreas Boehler      if(!isset($row['calid']))
1189f69bb449SAndreas Boehler        return false;
1190f69bb449SAndreas Boehler      return $row['calid'];
1191f69bb449SAndreas Boehler  }
1192f69bb449SAndreas Boehler
1193cb71a62aSAndreas Boehler  /**
1194cb71a62aSAndreas Boehler   * Return a given calendar as ICS feed, i.e. all events in one ICS file.
1195cb71a62aSAndreas Boehler   *
11967e0b8590SAndreas Boehler   * @param string $calid The calendar ID to retrieve
1197cb71a62aSAndreas Boehler   *
1198cb71a62aSAndreas Boehler   * @return mixed The calendar events as string or false
1199cb71a62aSAndreas Boehler   */
1200f69bb449SAndreas Boehler  public function getCalendarAsICSFeed($calid)
1201f69bb449SAndreas Boehler  {
1202f69bb449SAndreas Boehler      $calSettings = $this->getCalendarSettings($calid);
1203f69bb449SAndreas Boehler      if($calSettings === false)
1204f69bb449SAndreas Boehler        return false;
1205f69bb449SAndreas Boehler      $events = $this->getAllCalendarEvents($calid);
1206f69bb449SAndreas Boehler      if($events === false)
1207f69bb449SAndreas Boehler        return false;
1208f69bb449SAndreas Boehler
12097e0b8590SAndreas Boehler      // Load SabreDAV
12107e0b8590SAndreas Boehler      require_once(DOKU_PLUGIN.'davcal/vendor/autoload.php');
12117e0b8590SAndreas Boehler      $out = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//DAVCal//DAVCal for DokuWiki//EN\r\nCALSCALE:GREGORIAN\r\nX-WR-CALNAME:";
12127e0b8590SAndreas Boehler      $out .= $calSettings['displayname']."\r\n";
1213f69bb449SAndreas Boehler      foreach($events as $event)
1214f69bb449SAndreas Boehler      {
12157e0b8590SAndreas Boehler          $vcal = \Sabre\VObject\Reader::read($event['calendardata']);
12167e0b8590SAndreas Boehler          $evt = $vcal->VEVENT;
12177e0b8590SAndreas Boehler          $out .= $evt->serialize();
1218f69bb449SAndreas Boehler      }
12197e0b8590SAndreas Boehler      $out .= "END:VCALENDAR\r\n";
1220f69bb449SAndreas Boehler      return $out;
1221f69bb449SAndreas Boehler  }
1222f69bb449SAndreas Boehler
12237c7c6b0bSAndreas Boehler  /**
12247c7c6b0bSAndreas Boehler   * Retrieve a configuration option for the plugin
12257c7c6b0bSAndreas Boehler   *
12267c7c6b0bSAndreas Boehler   * @param string $key The key to query
122721d04f73SAndreas Boehler   * @return mixed The option set, null if not found
12287c7c6b0bSAndreas Boehler   */
12297c7c6b0bSAndreas Boehler  public function getConfig($key)
12307c7c6b0bSAndreas Boehler  {
12317c7c6b0bSAndreas Boehler      return $this->getConf($key);
12327c7c6b0bSAndreas Boehler  }
12337c7c6b0bSAndreas Boehler
1234a1a3b679SAndreas Boehler}
1235