Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube
This commit is contained in:
commit
0ec7458eb1
10 changed files with 249 additions and 57 deletions
|
@ -109,6 +109,16 @@ class calendar extends rcube_plugin
|
||||||
$this->register_action('freebusy-times', array($this, 'freebusy_times'));
|
$this->register_action('freebusy-times', array($this, 'freebusy_times'));
|
||||||
$this->register_action('randomdata', array($this, 'generate_randomdata'));
|
$this->register_action('randomdata', array($this, 'generate_randomdata'));
|
||||||
$this->register_action('print',array($this,'print_view'));
|
$this->register_action('print',array($this,'print_view'));
|
||||||
|
|
||||||
|
// remove undo information...
|
||||||
|
if ($undo = $_SESSION['calendar_event_undo']) {
|
||||||
|
// ...after timeout
|
||||||
|
$undo_time = $this->rc->config->get('undo_timeout', 0);
|
||||||
|
if ($undo['ts'] < time() - $undo_time) {
|
||||||
|
$this->rc->session->remove('calendar_event_undo');
|
||||||
|
// @TODO: do EXPUNGE on kolab objects?
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ($this->rc->task == 'settings') {
|
else if ($this->rc->task == 'settings') {
|
||||||
// add hooks for Calendar settings
|
// add hooks for Calendar settings
|
||||||
|
@ -436,9 +446,9 @@ class calendar extends rcube_plugin
|
||||||
*/
|
*/
|
||||||
function event_action()
|
function event_action()
|
||||||
{
|
{
|
||||||
$action = get_input_value('action', RCUBE_INPUT_POST);
|
$action = get_input_value('action', RCUBE_INPUT_GPC);
|
||||||
$event = get_input_value('e', RCUBE_INPUT_POST);
|
$event = get_input_value('e', RCUBE_INPUT_POST);
|
||||||
$success = $reload = false;
|
$success = $reload = $got_msg = false;
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case "new":
|
case "new":
|
||||||
|
@ -475,8 +485,42 @@ class calendar extends rcube_plugin
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "remove":
|
case "remove":
|
||||||
$removed = $this->driver->remove_event($event);
|
// remove previous deletes
|
||||||
|
$undo_time = $this->driver->undelete ? $this->rc->config->get('undo_timeout', 0) : 0;
|
||||||
|
$this->rc->session->remove('calendar_event_undo');
|
||||||
|
|
||||||
|
$success = $this->driver->remove_event($event, $undo_time < 1);
|
||||||
|
$reload = true;
|
||||||
|
|
||||||
|
if ($undo_time > 0 && $success) {
|
||||||
|
$_SESSION['calendar_event_undo'] = array('ts' => time(), 'data' => $event);
|
||||||
|
// display message with Undo link.
|
||||||
|
$msg = html::span(null, $this->gettext('successremoval'))
|
||||||
|
. ' ' . html::a(array('onclick' => sprintf("%s.http_request('event', 'action=undo', %s.display_message('', 'loading'))",
|
||||||
|
JS_OBJECT_NAME, JS_OBJECT_NAME)), rcube_label('undo'));
|
||||||
|
$this->rc->output->show_message($msg, 'confirmation', null, true, $undo_time);
|
||||||
|
}
|
||||||
|
else if ($success) {
|
||||||
|
$this->rc->output->show_message('calendar.successremoval', 'confirmation');
|
||||||
|
$got_msg = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "undo":
|
||||||
|
// Restore deleted event
|
||||||
|
$event = $_SESSION['calendar_event_undo']['data'];
|
||||||
$reload = true;
|
$reload = true;
|
||||||
|
|
||||||
|
if ($event)
|
||||||
|
$success = $this->driver->restore_event($event);
|
||||||
|
|
||||||
|
if ($success) {
|
||||||
|
$this->rc->session->remove('calendar_event_undo');
|
||||||
|
$this->rc->output->show_message('calendar.successrestore', 'confirmation');
|
||||||
|
$got_msg = true;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "dismiss":
|
case "dismiss":
|
||||||
|
@ -485,18 +529,19 @@ class calendar extends rcube_plugin
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// show confirmation/error message
|
||||||
|
if (!$got_msg) {
|
||||||
|
if ($success)
|
||||||
|
$this->rc->output->show_message('successfullysaved', 'confirmation');
|
||||||
|
else
|
||||||
|
$this->rc->output->show_message('calendar.errorsaving', 'error');
|
||||||
|
}
|
||||||
|
|
||||||
// unlock client
|
// unlock client
|
||||||
$this->rc->output->command('plugin.unlock_saving');
|
$this->rc->output->command('plugin.unlock_saving');
|
||||||
|
|
||||||
if ($success)
|
|
||||||
$this->rc->output->show_message('successfullysaved', 'confirmation');
|
|
||||||
else if ($removed)
|
|
||||||
$this->rc->output->show_message('calendar.successremoval', 'confirmation');
|
|
||||||
else
|
|
||||||
$this->rc->output->show_message('calendar.errorsaving', 'error');
|
|
||||||
|
|
||||||
// FIXME: update a single event object on the client instead of reloading the entire source
|
// FIXME: update a single event object on the client instead of reloading the entire source
|
||||||
if ($success && $reload || ($removed && $reload))
|
if ($success && $reload)
|
||||||
$this->rc->output->command('plugin.reload_calendar', array('source' => $event['calendar']));
|
$this->rc->output->command('plugin.reload_calendar', array('source' => $event['calendar']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ class caldav_driver extends calendar_driver
|
||||||
// FIXME Implement. Can be done via editEvent
|
// FIXME Implement. Can be done via editEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remove_event($event) {
|
public function remove_event($event, $force = true) {
|
||||||
// FIXME Implement.
|
// FIXME Implement.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,11 @@
|
||||||
*/
|
*/
|
||||||
abstract class calendar_driver
|
abstract class calendar_driver
|
||||||
{
|
{
|
||||||
// backend features
|
// features supported by backend
|
||||||
public $alarms = false;
|
public $alarms = false;
|
||||||
public $attendees = false;
|
public $attendees = false;
|
||||||
public $attachments = false;
|
public $attachments = false;
|
||||||
|
public $undelete = false; // event undelete action
|
||||||
public $categoriesimmutable = false;
|
public $categoriesimmutable = false;
|
||||||
public $alarm_types = array('DISPLAY');
|
public $alarm_types = array('DISPLAY');
|
||||||
|
|
||||||
|
@ -156,11 +157,27 @@ abstract class calendar_driver
|
||||||
/**
|
/**
|
||||||
* Remove a single event from the database
|
* Remove a single event from the database
|
||||||
*
|
*
|
||||||
* @param array Hash array with event properties:
|
* @param array Hash array with event properties:
|
||||||
* id: Event identifier
|
* id: Event identifier
|
||||||
|
* @param boolean Remove event irreversible (mark as deleted otherwise,
|
||||||
|
* if supported by the backend)
|
||||||
|
*
|
||||||
* @return boolean True on success, False on error
|
* @return boolean True on success, False on error
|
||||||
*/
|
*/
|
||||||
abstract function remove_event($event);
|
abstract function remove_event($event, $force = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores a single deleted event (if supported)
|
||||||
|
*
|
||||||
|
* @param array Hash array with event properties:
|
||||||
|
* id: Event identifier
|
||||||
|
*
|
||||||
|
* @return boolean True on success, False on error
|
||||||
|
*/
|
||||||
|
public function restore_event($event)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get events from source.
|
* Get events from source.
|
||||||
|
|
|
@ -513,10 +513,12 @@ class database_driver extends calendar_driver
|
||||||
/**
|
/**
|
||||||
* Remove a single event from the database
|
* Remove a single event from the database
|
||||||
*
|
*
|
||||||
* @param array Hash array with event properties
|
* @param array Hash array with event properties
|
||||||
|
* @param boolean Remove record irreversible (@TODO)
|
||||||
|
*
|
||||||
* @see Driver:remove_event()
|
* @see Driver:remove_event()
|
||||||
*/
|
*/
|
||||||
public function remove_event($event)
|
public function remove_event($event, $force = true)
|
||||||
{
|
{
|
||||||
if (!empty($this->calendars)) {
|
if (!empty($this->calendars)) {
|
||||||
$event += (array)$this->get_event($event['id']);
|
$event += (array)$this->get_event($event['id']);
|
||||||
|
|
|
@ -294,10 +294,17 @@ class kolab_calendar
|
||||||
* @see Driver:remove_event()
|
* @see Driver:remove_event()
|
||||||
* @return boolean True on success, False on error
|
* @return boolean True on success, False on error
|
||||||
*/
|
*/
|
||||||
public function delete_event($event)
|
public function delete_event($event, $force = true)
|
||||||
{
|
{
|
||||||
$deleted = false;
|
$deleted = false;
|
||||||
$deleteme = $this->storage->delete($event['id']);
|
|
||||||
|
if (!$force) {
|
||||||
|
// Get IMAP object ID
|
||||||
|
$imap_uid = $this->storage->_getStorageId($event['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$deleteme = $this->storage->delete($event['id'], $force);
|
||||||
|
|
||||||
if (PEAR::isError($deleteme)) {
|
if (PEAR::isError($deleteme)) {
|
||||||
raise_error(array(
|
raise_error(array(
|
||||||
'code' => 600, 'type' => 'php',
|
'code' => 600, 'type' => 'php',
|
||||||
|
@ -306,12 +313,67 @@ class kolab_calendar
|
||||||
true, false);
|
true, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Save IMAP object ID in session, will be used for restore action
|
||||||
|
if ($imap_uid)
|
||||||
|
$_SESSION['kolab_delete_uids'][$event['id']] = $imap_uid;
|
||||||
|
|
||||||
$deleted = true;
|
$deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $deleted;
|
return $deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore deleted event record
|
||||||
|
*
|
||||||
|
* @see Driver:undelete_event()
|
||||||
|
* @return boolean True on success, False on error
|
||||||
|
*/
|
||||||
|
public function restore_event($event)
|
||||||
|
{
|
||||||
|
$imap_uid = $_SESSION['kolab_delete_uids'][$event['id']];
|
||||||
|
|
||||||
|
if (!$imap_uid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$session = &Horde_Kolab_Session::singleton();
|
||||||
|
$imap = &$session->getImap();
|
||||||
|
|
||||||
|
if (is_a($imap, 'PEAR_Error')) {
|
||||||
|
$error = $imap;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$result = $imap->select($this->imap_folder);
|
||||||
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
|
$error = $result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$result = $imap->undeleteMessages($imap_uid);
|
||||||
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
|
$error = $result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// re-sync the cache
|
||||||
|
$this->storage->synchronize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
raise_error(array(
|
||||||
|
'code' => 600, 'type' => 'php',
|
||||||
|
'file' => __FILE__, 'line' => __LINE__,
|
||||||
|
'message' => "Error undeleting an event object(s) from the Kolab server:" . $error->getMessage()),
|
||||||
|
true, false);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rcmail = rcmail::get_instance();
|
||||||
|
$rcmail->session->remove('kolab_delete_uids');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simply fetch all records and store them in private member vars
|
* Simply fetch all records and store them in private member vars
|
||||||
|
|
|
@ -27,6 +27,7 @@ class kolab_driver extends calendar_driver
|
||||||
public $alarms = true;
|
public $alarms = true;
|
||||||
public $attendees = true;
|
public $attendees = true;
|
||||||
public $attachments = true;
|
public $attachments = true;
|
||||||
|
public $undelete = true;
|
||||||
public $categoriesimmutable = true;
|
public $categoriesimmutable = true;
|
||||||
|
|
||||||
private $rc;
|
private $rc;
|
||||||
|
@ -292,13 +293,15 @@ class kolab_driver extends calendar_driver
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a single event from the database
|
* Remove a single event
|
||||||
*
|
*
|
||||||
* @param array Hash array with event properties:
|
* @param array Hash array with event properties:
|
||||||
* id: Event identifier
|
* id: Event identifier
|
||||||
|
* @param boolean Remove record(s) irreversible (mark as deleted otherwise)
|
||||||
|
*
|
||||||
* @return boolean True on success, False on error
|
* @return boolean True on success, False on error
|
||||||
*/
|
*/
|
||||||
public function remove_event($event)
|
public function remove_event($event, $force = true)
|
||||||
{
|
{
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
|
@ -331,7 +334,7 @@ class kolab_driver extends calendar_driver
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // 'all' is default
|
default: // 'all' is default
|
||||||
$success = $storage->delete_event($master);
|
$success = $storage->delete_event($master, $force);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,6 +345,22 @@ class kolab_driver extends calendar_driver
|
||||||
return $success;
|
return $success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore a single deleted event
|
||||||
|
*
|
||||||
|
* @param array Hash array with event properties:
|
||||||
|
* id: Event identifier
|
||||||
|
* @return boolean True on success, False on error
|
||||||
|
*/
|
||||||
|
public function restore_event($event)
|
||||||
|
{
|
||||||
|
if ($storage = $this->calendars[$event['calendar']]) {
|
||||||
|
return $storage->restore_event($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to update an event object depending on the given savemode
|
* Wrapper to update an event object depending on the given savemode
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -100,15 +100,16 @@ $labels['tabattendees'] = 'Participants';
|
||||||
$labels['tabattachments'] = 'Attachments';
|
$labels['tabattachments'] = 'Attachments';
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
$labels['deleteventconfirm'] = "Do you really want to delete this event?";
|
$labels['deleteventconfirm'] = 'Do you really want to delete this event?';
|
||||||
$labels['deletecalendarconfirm'] = "Do you really want to delete this calendar with all its events?";
|
$labels['deletecalendarconfirm'] = 'Do you really want to delete this calendar with all its events?';
|
||||||
$labels['savingdata'] = "Saving data...";
|
$labels['savingdata'] = 'Saving data...';
|
||||||
$labels['errorsaving'] = "Failed to save changes";
|
$labels['errorsaving'] = 'Failed to save changes.';
|
||||||
$labels['operationfailed'] = "The requested operation failed";
|
$labels['operationfailed'] = 'The requested operation failed.';
|
||||||
$labels['invalideventdates'] = "Invalid dates entered! Please check your input.";
|
$labels['invalideventdates'] = 'Invalid dates entered! Please check your input.';
|
||||||
$labels['invalidcalendarproperties'] = "Invalid calendar properties! Please set a valid name.";
|
$labels['invalidcalendarproperties'] = 'Invalid calendar properties! Please set a valid name.';
|
||||||
$labels['searchnoresults'] = 'No events found in the selected calendars';
|
$labels['searchnoresults'] = 'No events found in the selected calendars.';
|
||||||
$labels['successremoval'] = "The event was deleted successfully";
|
$labels['successremoval'] = 'The event has been deleted successfully.';
|
||||||
|
$labels['successrestore'] = 'The event has been restored successfully.';
|
||||||
|
|
||||||
// recurrence form
|
// recurrence form
|
||||||
$labels['repeat'] = 'Repeat';
|
$labels['repeat'] = 'Repeat';
|
||||||
|
|
|
@ -163,17 +163,11 @@ class kolab_addressbook_ui
|
||||||
$hidden_fields[] = array('name' => '_parent', 'value' => $path_imap);
|
$hidden_fields[] = array('name' => '_parent', 'value' => $path_imap);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$radio1 = new html_radiobutton(array('name' => '_parent', 'value' => ''));
|
$select = rcube_kolab::folder_selector('contact', array('name' => '_parent'));
|
||||||
$radio2 = new html_radiobutton(array('name' => '_parent', 'value' => $path_imap));
|
|
||||||
|
|
||||||
$html_path = str_replace($delim, ' » ', $path);
|
|
||||||
|
|
||||||
$folderpath = $radio1->show($path_imap) . Q(rcube_label('none')) . ' '
|
|
||||||
.$radio2->show($path_imap) . Q($html_path);
|
|
||||||
|
|
||||||
$form['props']['fieldsets']['location']['content']['path'] = array(
|
$form['props']['fieldsets']['location']['content']['path'] = array(
|
||||||
'label' => $this->plugin->gettext('parentbook'),
|
'label' => $this->plugin->gettext('parentbook'),
|
||||||
'value' => $folderpath,
|
'value' => $select->show($path_imap),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,6 +649,10 @@ class rcube_kolab_contacts extends rcube_addressbook
|
||||||
if (is_a($result, 'PEAR_Error')) {
|
if (is_a($result, 'PEAR_Error')) {
|
||||||
$error = $result;
|
$error = $result;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$this->_connect();
|
||||||
|
$this->contactstorage->synchronize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -377,4 +377,52 @@ class rcube_kolab
|
||||||
return 'personal';
|
return 'personal';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a SELECT field with folders list
|
||||||
|
*
|
||||||
|
* @param string $type Folder type
|
||||||
|
* @param array $attrs SELECT field attributes (e.g. name)
|
||||||
|
*
|
||||||
|
* @return html_select SELECT object
|
||||||
|
*/
|
||||||
|
public static function folder_selector($type, $attrs)
|
||||||
|
{
|
||||||
|
// get all folders of specified type
|
||||||
|
$folders = self::get_folders($type);
|
||||||
|
|
||||||
|
$names = array();
|
||||||
|
foreach ($folders as $c_folder)
|
||||||
|
$names[$c_folder->name] = rcube_charset_convert($c_folder->name, 'UTF7-IMAP');
|
||||||
|
asort($names, SORT_LOCALE_STRING);
|
||||||
|
|
||||||
|
$folders = array_keys($names);
|
||||||
|
$names = array();
|
||||||
|
|
||||||
|
// Build SELECT field of parent folder
|
||||||
|
$select = new html_select($attrs);
|
||||||
|
$select->add('---', '');
|
||||||
|
|
||||||
|
foreach ($folders as $name) {
|
||||||
|
$imap_name = $name;
|
||||||
|
$name = $origname = self::object_name($name);
|
||||||
|
|
||||||
|
// find folder prefix to truncate
|
||||||
|
for ($i = count($names)-1; $i >= 0; $i--) {
|
||||||
|
if (strpos($name, $names[$i].' » ') === 0) {
|
||||||
|
$length = strlen($names[$i].' » ');
|
||||||
|
$prefix = substr($name, 0, $length);
|
||||||
|
$count = count(explode(' » ', $prefix));
|
||||||
|
$name = str_repeat(' ', $count-1) . '» ' . substr($name, $length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$names[] = $origname;
|
||||||
|
|
||||||
|
$select->add($name, $imap_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $select;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue