2011-05-20 19:04:25 +02:00
|
|
|
<?php
|
2011-08-21 12:48:33 +02:00
|
|
|
|
|
|
|
/**
|
2011-11-21 11:20:48 +01:00
|
|
|
* Kolab calendar storage class
|
2011-08-21 12:48:33 +02:00
|
|
|
*
|
2011-11-21 11:20:48 +01:00
|
|
|
* @version @package_version@
|
2011-12-07 12:51:23 +01:00
|
|
|
* @author Thomas Bruederli <bruederli@kolabsys.com>
|
2011-08-21 12:48:33 +02:00
|
|
|
* @author Aleksander Machniak <machniak@kolabsys.com>
|
|
|
|
*
|
2012-03-30 19:14:38 +02:00
|
|
|
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
|
2011-08-21 12:48:33 +02:00
|
|
|
*
|
2011-10-27 10:20:46 +02:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
2011-08-21 12:48:33 +02:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-10-27 10:20:46 +02:00
|
|
|
* GNU Affero General Public License for more details.
|
2011-08-21 12:48:33 +02:00
|
|
|
*
|
2011-10-27 10:20:46 +02:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2011-08-21 12:48:33 +02:00
|
|
|
*/
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
|
2011-05-23 10:28:17 +02:00
|
|
|
class kolab_calendar
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
const COLOR_KEY_SHARED = '/shared/vendor/kolab/color';
|
|
|
|
const COLOR_KEY_PRIVATE = '/shared/vendor/kolab/color';
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
public $id;
|
|
|
|
public $ready = false;
|
|
|
|
public $readonly = true;
|
2011-07-01 21:08:12 +02:00
|
|
|
public $attachments = true;
|
2011-07-07 08:23:49 +02:00
|
|
|
public $alarms = false;
|
2011-09-14 16:02:07 +02:00
|
|
|
public $categories = array();
|
2011-09-19 09:50:13 +02:00
|
|
|
public $storage;
|
2011-06-27 15:49:51 +02:00
|
|
|
|
2011-06-18 18:40:12 -06:00
|
|
|
private $cal;
|
2011-05-20 19:04:25 +02:00
|
|
|
private $events;
|
|
|
|
private $id2uid;
|
|
|
|
private $imap_folder = 'INBOX/Calendar';
|
2011-07-31 11:13:13 +02:00
|
|
|
private $search_fields = array('title', 'description', 'location', '_attendees');
|
2011-05-27 18:41:01 +02:00
|
|
|
private $sensitivity_map = array('public', 'private', 'confidential');
|
2011-06-13 16:00:55 +03:00
|
|
|
|
2011-06-27 15:49:51 +02:00
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
/**
|
|
|
|
* Default constructor
|
|
|
|
*/
|
2011-06-18 18:40:12 -06:00
|
|
|
public function __construct($imap_folder, $calendar)
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
2011-06-18 18:40:12 -06:00
|
|
|
$this->cal = $calendar;
|
2011-06-27 15:49:51 +02:00
|
|
|
|
2011-06-15 11:23:59 +02:00
|
|
|
if (strlen($imap_folder))
|
2011-05-20 19:04:25 +02:00
|
|
|
$this->imap_folder = $imap_folder;
|
2011-06-15 11:23:59 +02:00
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
// ID is derrived from folder name
|
2012-03-30 19:14:38 +02:00
|
|
|
$this->id = kolab_storage::folder_id($this->imap_folder);
|
2011-05-20 19:04:25 +02:00
|
|
|
|
|
|
|
// fetch objects from the given IMAP folder
|
2012-03-30 19:14:38 +02:00
|
|
|
$this->storage = kolab_storage::get_folder($this->imap_folder);
|
2012-04-04 13:01:59 +02:00
|
|
|
$this->ready = $this->storage && !PEAR::isError($this->storage);
|
2011-06-28 10:32:52 +02:00
|
|
|
|
2011-07-07 08:23:49 +02:00
|
|
|
// Set readonly and alarms flags according to folder permissions
|
2011-06-28 10:32:52 +02:00
|
|
|
if ($this->ready) {
|
|
|
|
if ($this->get_owner() == $_SESSION['username']) {
|
|
|
|
$this->readonly = false;
|
2011-07-07 08:23:49 +02:00
|
|
|
$this->alarms = true;
|
2011-06-28 10:32:52 +02:00
|
|
|
}
|
|
|
|
else {
|
2012-03-30 19:14:38 +02:00
|
|
|
$rights = $this->storage->get_acl();
|
2012-04-04 13:01:59 +02:00
|
|
|
if ($rights && !PEAR::isError($rights)) {
|
2011-07-29 15:08:00 +02:00
|
|
|
if (strpos($rights, 'i') !== false)
|
2011-07-25 12:33:44 +02:00
|
|
|
$this->readonly = false;
|
|
|
|
}
|
2011-06-28 10:32:52 +02:00
|
|
|
}
|
2011-07-31 14:40:52 +02:00
|
|
|
|
|
|
|
// user-specific alarms settings win
|
|
|
|
$prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
|
|
|
if (isset($prefs[$this->id]['showalarms']))
|
|
|
|
$this->alarms = $prefs[$this->id]['showalarms'];
|
2011-06-28 10:32:52 +02:00
|
|
|
}
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Getter for a nice and human readable name for this calendar
|
|
|
|
* See http://wiki.kolab.org/UI-Concepts/Folder-Listing for reference
|
|
|
|
*
|
|
|
|
* @return string Name of this calendar
|
|
|
|
*/
|
|
|
|
public function get_name()
|
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
$folder = kolab_storage::object_name($this->imap_folder, $this->namespace);
|
2011-06-28 10:32:52 +02:00
|
|
|
return $folder;
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
2011-06-27 15:49:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Getter for the IMAP folder name
|
|
|
|
*
|
|
|
|
* @return string Name of the IMAP folder
|
|
|
|
*/
|
|
|
|
public function get_realname()
|
|
|
|
{
|
|
|
|
return $this->imap_folder;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-28 10:32:52 +02:00
|
|
|
/**
|
|
|
|
* Getter for the IMAP folder owner
|
|
|
|
*
|
|
|
|
* @return string Name of the folder owner
|
|
|
|
*/
|
|
|
|
public function get_owner()
|
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
return $this->storage->get_owner();
|
2011-06-28 10:32:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Getter for the name of the namespace to which the IMAP folder belongs
|
|
|
|
*
|
|
|
|
* @return string Name of the namespace (personal, other, shared)
|
|
|
|
*/
|
|
|
|
public function get_namespace()
|
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
return $this->storage->get_namespace();
|
2011-06-28 10:32:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-13 14:38:54 -06:00
|
|
|
/**
|
|
|
|
* Getter for the top-end calendar folder name (not the entire path)
|
|
|
|
*
|
|
|
|
* @return string Name of this calendar
|
|
|
|
*/
|
|
|
|
public function get_foldername()
|
|
|
|
{
|
|
|
|
$parts = explode('/', $this->imap_folder);
|
2012-01-23 10:16:30 +01:00
|
|
|
return rcube_charset::convert(end($parts), 'UTF7-IMAP');
|
2011-06-13 14:38:54 -06:00
|
|
|
}
|
2011-05-20 19:04:25 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return color to display this calendar
|
|
|
|
*/
|
2011-06-27 15:49:51 +02:00
|
|
|
public function get_color()
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
2011-08-26 23:24:49 +02:00
|
|
|
// color is defined in folder METADATA
|
2012-03-30 19:14:38 +02:00
|
|
|
$metadata = $this->storage->get_metadata(array(self::COLOR_KEY_PRIVATE, self::COLOR_KEY_SHARED));
|
|
|
|
if (($color = $metadata[self::COLOR_KEY_PRIVATE]) || ($color = $metadata[self::COLOR_KEY_SHARED])) {
|
2011-08-26 23:24:49 +02:00
|
|
|
return $color;
|
|
|
|
}
|
2011-09-30 17:28:29 +02:00
|
|
|
|
2011-09-16 15:52:09 +02:00
|
|
|
// calendar color is stored in user prefs (temporary solution)
|
2011-06-27 15:49:51 +02:00
|
|
|
$prefs = $this->cal->rc->config->get('kolab_calendars', array());
|
|
|
|
|
|
|
|
if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color']))
|
|
|
|
return $prefs[$this->id]['color'];
|
|
|
|
|
|
|
|
return 'cc0000';
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
2011-06-27 15:49:51 +02:00
|
|
|
|
2011-07-16 17:14:36 +02:00
|
|
|
/**
|
2012-03-30 19:14:38 +02:00
|
|
|
* Return the corresponding kolab_storage_folder instance
|
2011-07-16 17:14:36 +02:00
|
|
|
*/
|
|
|
|
public function get_folder()
|
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
return $this->storage;
|
2011-07-16 17:14:36 +02:00
|
|
|
}
|
|
|
|
|
2011-07-01 21:08:12 +02:00
|
|
|
/**
|
|
|
|
* Getter for the attachment body
|
|
|
|
*/
|
|
|
|
public function get_attachment_body($id)
|
|
|
|
{
|
|
|
|
return $this->storage->getAttachment($id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
/**
|
|
|
|
* Getter for a single event object
|
|
|
|
*/
|
|
|
|
public function get_event($id)
|
|
|
|
{
|
|
|
|
$this->_fetch_events();
|
2011-06-29 19:42:56 +02:00
|
|
|
|
|
|
|
// event not found, maybe a recurring instance is requested
|
|
|
|
if (!$this->events[$id]) {
|
|
|
|
$master_id = preg_replace('/-\d+$/', '', $id);
|
|
|
|
if ($this->events[$master_id] && $this->events[$master_id]['recurrence']) {
|
|
|
|
$master = $this->events[$master_id];
|
2011-07-04 12:50:47 +02:00
|
|
|
$this->_get_recurring_events($master, $master['start'], $master['start'] + 86400 * 365 * 10, $id);
|
2011-06-29 19:42:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
return $this->events[$id];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param integer Event's new start (unix timestamp)
|
|
|
|
* @param integer Event's new end (unix timestamp)
|
2011-06-13 18:41:32 -06:00
|
|
|
* @param string Search query (optional)
|
2011-07-19 14:54:13 +03:00
|
|
|
* @param boolean Strip virtual events (optional)
|
2011-05-20 19:04:25 +02:00
|
|
|
* @return array A list of event records
|
|
|
|
*/
|
2011-07-19 14:54:13 +03:00
|
|
|
public function list_events($start, $end, $search = null, $virtual = 1)
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
|
|
|
$this->_fetch_events();
|
2011-06-13 18:41:32 -06:00
|
|
|
|
2011-07-20 19:15:21 +02:00
|
|
|
if (!empty($search))
|
|
|
|
$search = mb_strtolower($search);
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
$events = array();
|
|
|
|
foreach ($this->events as $id => $event) {
|
2011-09-14 16:02:07 +02:00
|
|
|
// remember seen categories
|
|
|
|
if ($event['categories'])
|
|
|
|
$this->categories[$event['categories']]++;
|
|
|
|
|
2011-06-29 14:08:05 +02:00
|
|
|
// filter events by search query
|
2011-06-13 18:41:32 -06:00
|
|
|
if (!empty($search)) {
|
2011-06-29 14:08:05 +02:00
|
|
|
$hit = false;
|
|
|
|
foreach ($this->search_fields as $col) {
|
2011-07-31 11:13:13 +02:00
|
|
|
$sval = is_array($col) ? $event[$col[0]][$col[1]] : $event[$col];
|
|
|
|
if (empty($sval))
|
2011-06-29 14:08:05 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// do a simple substring matching (to be improved)
|
2011-07-31 11:13:13 +02:00
|
|
|
$val = mb_strtolower($sval);
|
2011-06-29 14:08:05 +02:00
|
|
|
if (strpos($val, $search) !== false) {
|
|
|
|
$hit = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-06-13 18:41:32 -06:00
|
|
|
|
2011-06-29 14:08:05 +02:00
|
|
|
if (!$hit) // skip this event if not match with search term
|
|
|
|
continue;
|
2011-06-13 18:41:32 -06:00
|
|
|
}
|
|
|
|
|
2011-05-30 22:57:36 +02:00
|
|
|
// list events in requested time window
|
2011-05-22 17:29:09 +02:00
|
|
|
if ($event['start'] <= $end && $event['end'] >= $start) {
|
2011-07-31 11:13:13 +02:00
|
|
|
unset($event['_attendees']);
|
2011-05-20 19:04:25 +02:00
|
|
|
$events[] = $event;
|
|
|
|
}
|
2011-05-30 22:57:36 +02:00
|
|
|
|
2011-06-29 19:42:56 +02:00
|
|
|
// resolve recurring events
|
2011-07-19 14:54:13 +03:00
|
|
|
if ($event['recurrence'] && $virtual == 1) {
|
2011-07-31 11:13:13 +02:00
|
|
|
unset($event['_attendees']);
|
2011-06-29 19:42:56 +02:00
|
|
|
$events = array_merge($events, $this->_get_recurring_events($event, $start, $end));
|
2011-05-30 22:57:36 +02:00
|
|
|
}
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
2011-07-01 21:08:12 +02:00
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
return $events;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new event record
|
|
|
|
*
|
2011-07-27 16:06:06 +02:00
|
|
|
* @see calendar_driver::new_event()
|
2011-06-19 14:46:38 +03:00
|
|
|
*
|
2011-05-20 19:04:25 +02:00
|
|
|
* @return mixed The created record ID on success, False on error
|
|
|
|
*/
|
|
|
|
public function insert_event($event)
|
|
|
|
{
|
2011-06-29 15:36:39 +02:00
|
|
|
if (!is_array($event))
|
|
|
|
return false;
|
2011-07-01 21:08:12 +02:00
|
|
|
|
2011-06-29 15:36:39 +02:00
|
|
|
//generate new event from RC input
|
|
|
|
$object = $this->_from_rcube_event($event);
|
2012-03-30 19:14:38 +02:00
|
|
|
$saved = $this->storage->save($object, 'event');
|
2011-06-29 15:36:39 +02:00
|
|
|
|
2012-04-04 13:01:59 +02:00
|
|
|
if (!$saved || PEAR::isError($saved)) {
|
2011-06-29 15:36:39 +02:00
|
|
|
raise_error(array(
|
|
|
|
'code' => 600, 'type' => 'php',
|
|
|
|
'file' => __FILE__, 'line' => __LINE__,
|
|
|
|
'message' => "Error saving event object to Kolab server:" . $saved->getMessage()),
|
|
|
|
true, false);
|
|
|
|
$saved = false;
|
|
|
|
}
|
2011-07-27 16:06:06 +02:00
|
|
|
else {
|
2011-08-05 20:54:57 +02:00
|
|
|
$event['id'] = $event['uid'];
|
2011-07-27 16:06:06 +02:00
|
|
|
$this->events[$event['uid']] = $event;
|
|
|
|
}
|
2011-06-29 15:36:39 +02:00
|
|
|
|
2011-06-13 16:00:55 +03:00
|
|
|
return $saved;
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update a specific event record
|
|
|
|
*
|
2011-07-27 16:06:06 +02:00
|
|
|
* @see calendar_driver::new_event()
|
2011-05-20 19:04:25 +02:00
|
|
|
* @return boolean True on success, False on error
|
|
|
|
*/
|
|
|
|
|
|
|
|
public function update_event($event)
|
|
|
|
{
|
2011-06-29 15:36:39 +02:00
|
|
|
$updated = false;
|
2012-04-04 13:01:59 +02:00
|
|
|
$old = $this->storage->get_object($event['id']);
|
|
|
|
if (!$old || PEAR::isError($old))
|
2011-09-19 09:50:13 +02:00
|
|
|
return false;
|
|
|
|
|
2011-09-01 00:16:59 +02:00
|
|
|
$old['recurrence'] = ''; # clear old field, could have been removed in new, too
|
2012-03-30 19:14:38 +02:00
|
|
|
$object = $this->_from_rcube_event($event, $old);
|
|
|
|
$saved = $this->storage->save($object, 'event', $event['id']);
|
2011-08-01 20:39:11 +02:00
|
|
|
|
2012-04-04 13:01:59 +02:00
|
|
|
if (!$saved || PEAR::isError($saved)) {
|
2011-06-29 15:36:39 +02:00
|
|
|
raise_error(array(
|
|
|
|
'code' => 600, 'type' => 'php',
|
|
|
|
'file' => __FILE__, 'line' => __LINE__,
|
|
|
|
'message' => "Error saving event object to Kolab server:" . $saved->getMessage()),
|
|
|
|
true, false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$updated = true;
|
2011-07-27 16:06:06 +02:00
|
|
|
$this->events[$event['id']] = $this->_to_rcube_event($object);
|
2011-06-29 15:36:39 +02:00
|
|
|
}
|
|
|
|
|
2011-06-13 16:36:46 +03:00
|
|
|
return $updated;
|
|
|
|
}
|
|
|
|
|
2011-06-29 15:36:39 +02:00
|
|
|
/**
|
|
|
|
* Delete an event record
|
|
|
|
*
|
2011-07-27 16:06:06 +02:00
|
|
|
* @see calendar_driver::remove_event()
|
2011-06-29 15:36:39 +02:00
|
|
|
* @return boolean True on success, False on error
|
|
|
|
*/
|
2011-07-18 15:28:57 +02:00
|
|
|
public function delete_event($event, $force = true)
|
2011-06-13 16:36:46 +03:00
|
|
|
{
|
2012-04-04 13:01:59 +02:00
|
|
|
$deleted = $this->storage->delete($event['id'], $force);
|
2011-07-18 15:28:57 +02:00
|
|
|
|
2012-04-04 13:01:59 +02:00
|
|
|
if (!$deleted || PEAR::isError($deleted)) {
|
2011-06-29 15:36:39 +02:00
|
|
|
raise_error(array(
|
|
|
|
'code' => 600, 'type' => 'php',
|
|
|
|
'file' => __FILE__, 'line' => __LINE__,
|
2012-04-04 13:01:59 +02:00
|
|
|
'message' => "Error deleting event object from Kolab server"),
|
2011-06-29 15:36:39 +02:00
|
|
|
true, false);
|
|
|
|
}
|
2011-07-18 15:28:57 +02:00
|
|
|
|
2011-06-14 14:52:20 +03:00
|
|
|
return $deleted;
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
|
|
|
|
2011-07-18 15:28:57 +02:00
|
|
|
/**
|
|
|
|
* Restore deleted event record
|
|
|
|
*
|
2011-07-27 16:06:06 +02:00
|
|
|
* @see calendar_driver::undelete_event()
|
2011-07-18 15:28:57 +02:00
|
|
|
* @return boolean True on success, False on error
|
|
|
|
*/
|
|
|
|
public function restore_event($event)
|
|
|
|
{
|
2012-04-04 13:01:59 +02:00
|
|
|
// TODO: re-implement this with new kolab_storege backend
|
|
|
|
return false;
|
2011-07-18 15:28:57 +02:00
|
|
|
}
|
2011-05-20 19:04:25 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Simply fetch all records and store them in private member vars
|
|
|
|
* We thereby rely on cahcing done by the Horde classes
|
|
|
|
*/
|
|
|
|
private function _fetch_events()
|
|
|
|
{
|
|
|
|
if (!isset($this->events)) {
|
|
|
|
$this->events = array();
|
2012-03-30 19:14:38 +02:00
|
|
|
|
|
|
|
foreach ((array)$this->storage->get_objects() as $record) {
|
2011-05-20 19:04:25 +02:00
|
|
|
$event = $this->_to_rcube_event($record);
|
|
|
|
$this->events[$event['id']] = $event;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-29 19:42:56 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create instances of a recurring event
|
|
|
|
*/
|
2011-09-28 17:14:29 +02:00
|
|
|
public function _get_recurring_events($event, $start, $end, $event_id = null)
|
2011-06-29 19:42:56 +02:00
|
|
|
{
|
2011-10-14 11:58:42 +02:00
|
|
|
// include library class
|
|
|
|
require_once($this->cal->home . '/lib/calendar_recurrence.php');
|
2011-06-29 19:42:56 +02:00
|
|
|
|
2011-10-14 11:58:42 +02:00
|
|
|
$recurrence = new calendar_recurrence($this->cal, $event);
|
2011-06-29 19:42:56 +02:00
|
|
|
|
|
|
|
$events = array();
|
|
|
|
$duration = $event['end'] - $event['start'];
|
|
|
|
$i = 0;
|
2011-10-14 11:58:42 +02:00
|
|
|
while ($rec_start = $recurrence->next_start()) {
|
2011-06-29 19:42:56 +02:00
|
|
|
$rec_end = $rec_start + $duration;
|
|
|
|
$rec_id = $event['id'] . '-' . ++$i;
|
|
|
|
|
|
|
|
// add to output if in range
|
|
|
|
if (($rec_start <= $end && $rec_end >= $start) || ($event_id && $rec_id == $event_id)) {
|
|
|
|
$rec_event = $event;
|
|
|
|
$rec_event['id'] = $rec_id;
|
|
|
|
$rec_event['recurrence_id'] = $event['id'];
|
|
|
|
$rec_event['start'] = $rec_start;
|
|
|
|
$rec_event['end'] = $rec_end;
|
|
|
|
$rec_event['_instance'] = $i;
|
|
|
|
$events[] = $rec_event;
|
|
|
|
|
|
|
|
if ($rec_id == $event_id) {
|
|
|
|
$this->events[$rec_id] = $rec_event;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ($rec_start > $end) // stop loop if out of range
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $events;
|
|
|
|
}
|
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
/**
|
|
|
|
* Convert from Kolab_Format to internal representation
|
|
|
|
*/
|
2012-03-30 19:14:38 +02:00
|
|
|
private function _to_rcube_event($record)
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
$record['id'] = $record['uid'];
|
|
|
|
$record['calendar'] = $this->id;
|
2011-07-01 21:08:12 +02:00
|
|
|
|
2012-03-30 19:14:38 +02:00
|
|
|
// convert from DateTime to unix timestamp
|
|
|
|
if (is_a($record['start'], 'DateTime'))
|
|
|
|
$record['start'] = $record['start']->format('U');
|
|
|
|
if (is_a($record['end'], 'DateTime'))
|
|
|
|
$record['end'] = $record['end']->format('U');
|
|
|
|
|
|
|
|
// all-day events go from 12:00 - 13:00
|
|
|
|
if ($record['end'] <= $record['start'] && $record['allday'])
|
|
|
|
$record['end'] = $record['start'] + 3600;
|
2011-07-01 21:08:12 +02:00
|
|
|
|
|
|
|
if (!empty($rec['_attachments'])) {
|
|
|
|
foreach ($rec['_attachments'] as $name => $attachment) {
|
|
|
|
// @TODO: 'type' and 'key' are the only supported (no 'size')
|
|
|
|
$attachments[] = array(
|
|
|
|
'id' => $attachment['key'],
|
|
|
|
'mimetype' => $attachment['type'],
|
|
|
|
'name' => $name,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2012-03-30 19:14:38 +02:00
|
|
|
|
|
|
|
$sensitivity_map = array_flip($this->sensitivity_map);
|
|
|
|
$record['sensitivity'] = intval($sensitivity_map[$record['sensitivity']]);
|
|
|
|
|
2011-09-14 16:02:07 +02:00
|
|
|
// Roundcube only supports one category assignment
|
2012-03-30 19:14:38 +02:00
|
|
|
if (is_array($record['categories']))
|
|
|
|
$record['categories'] = $record['categories'][0];
|
|
|
|
|
|
|
|
// remove internals
|
|
|
|
unset($record['_mailbox'], $record['_msguid'], $record['_formatobj'], $record['_attachments']);
|
|
|
|
|
|
|
|
return $record;
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
|
|
|
|
2011-06-18 09:05:48 +03:00
|
|
|
/**
|
2011-05-20 19:04:25 +02:00
|
|
|
* Convert the given event record into a data structure that can be passed to Kolab_Storage backend for saving
|
|
|
|
* (opposite of self::_to_rcube_event())
|
|
|
|
*/
|
2012-03-30 19:14:38 +02:00
|
|
|
private function _from_rcube_event($event, $old = array())
|
2011-05-20 19:04:25 +02:00
|
|
|
{
|
2012-03-30 19:14:38 +02:00
|
|
|
$object = &$event;
|
|
|
|
|
2011-07-01 21:08:12 +02:00
|
|
|
// in Horde attachments are indexed by name
|
|
|
|
$object['_attachments'] = array();
|
|
|
|
if (!empty($event['attachments'])) {
|
2011-07-06 19:53:34 +02:00
|
|
|
$collisions = array();
|
2011-07-01 21:08:12 +02:00
|
|
|
foreach ($event['attachments'] as $idx => $attachment) {
|
2011-07-05 19:45:09 +02:00
|
|
|
// Roundcube ID has nothing to do with Horde ID, remove it
|
2011-07-06 19:53:34 +02:00
|
|
|
if ($attachment['content'])
|
|
|
|
unset($attachment['id']);
|
2011-08-01 20:39:11 +02:00
|
|
|
|
2011-07-06 19:53:34 +02:00
|
|
|
// Horde code assumes that there will be no more than
|
|
|
|
// one file with the same name: make filenames unique
|
|
|
|
$filename = $attachment['name'];
|
|
|
|
if ($collisions[$filename]++) {
|
|
|
|
$ext = preg_match('/(\.[a-z0-9]{1,6})$/i', $filename, $m) ? $m[1] : null;
|
|
|
|
$attachment['name'] = basename($filename, $ext) . '-' . $collisions[$filename] . $ext;
|
|
|
|
}
|
2011-08-01 20:39:11 +02:00
|
|
|
|
|
|
|
// set type parameter
|
|
|
|
if ($attachment['mimetype'])
|
|
|
|
$attachment['type'] = $attachment['mimetype'];
|
|
|
|
|
2011-07-01 21:08:12 +02:00
|
|
|
$object['_attachments'][$attachment['name']] = $attachment;
|
|
|
|
unset($event['attachments'][$idx]);
|
|
|
|
}
|
|
|
|
}
|
2011-08-01 20:39:11 +02:00
|
|
|
|
2012-03-30 19:14:38 +02:00
|
|
|
// translate sensitivity property
|
|
|
|
$event['sensitivity'] = $this->sensitivity_map[$event['sensitivity']];
|
|
|
|
|
|
|
|
// set current user as ORGANIZER
|
2012-04-03 23:08:24 +02:00
|
|
|
$identity = $this->cal->rc->user->get_identity();
|
|
|
|
if (empty($event['attendees']) && $identity['email'])
|
2012-03-30 19:14:38 +02:00
|
|
|
$event['attendees'] = array(array('role' => 'ORGANIZER', 'name' => $identity['name'], 'email' => $identity['email']));
|
|
|
|
|
2012-04-03 23:08:24 +02:00
|
|
|
$event['_owner'] = $identity['email'];
|
|
|
|
|
2012-03-30 19:14:38 +02:00
|
|
|
// copy meta data (starting with _) from old object
|
|
|
|
foreach ((array)$old as $key => $val) {
|
|
|
|
if (!isset($event[$key]) && $key[0] == '_')
|
|
|
|
$event[$key] = $val;
|
2011-07-08 17:29:22 +02:00
|
|
|
}
|
2011-07-01 21:08:12 +02:00
|
|
|
|
2012-03-30 19:14:38 +02:00
|
|
|
return $event;
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|
|
|
|
|
2011-06-14 14:52:20 +03:00
|
|
|
|
2011-05-20 19:04:25 +02:00
|
|
|
}
|