Added possibility to undo last event delete action (kolab driver only)
This commit is contained in:
parent
b7564ade58
commit
83a95c9aee
7 changed files with 195 additions and 49 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';
|
||||||
|
|
Loading…
Add table
Reference in a new issue