Fix merging attachments list on event/task update from iTip (#5342)

Reviewers: #roundcube_kolab_plugins_developers, vanmeeuwen

Reviewed By: #roundcube_kolab_plugins_developers, vanmeeuwen

Subscribers: vanmeeuwen

Projects: #roundcube_kolab_plugins

Differential Revision: https://git.kolab.org/D96
This commit is contained in:
Aleksander Machniak 2016-03-17 16:33:18 +01:00
parent ed93508c8a
commit fc93828311
5 changed files with 83 additions and 80 deletions

View file

@ -2996,6 +2996,13 @@ class calendar extends rcube_plugin
// set status=CANCELLED on CANCEL messages
if ($event['_method'] == 'CANCEL')
$event['status'] = 'CANCELLED';
// update attachments list, allow attachments update only on REQUEST (#5342)
if ($event['_method'] == 'REQUEST')
$event['deleted_attachments'] = true;
else
unset($event['attachments']);
// show me as free when declined (#1670)
if ($status == 'declined' || $event['status'] == 'CANCELLED' || $event_attendee['role'] == 'NON-PARTICIPANT')
$event['free_busy'] = 'free';

View file

@ -1972,46 +1972,7 @@ class kolab_driver extends calendar_driver
*/
public static function from_rcube_event($event, $old = array())
{
// in kolab_storage attachments are indexed by content-id
if (is_array($event['attachments']) || !empty($event['deleted_attachments'])) {
$event['_attachments'] = array();
foreach ($event['attachments'] as $attachment) {
$key = null;
// Roundcube ID has nothing to do with the storage ID, remove it
if ($attachment['content'] || $attachment['path']) {
unset($attachment['id']);
}
else {
foreach ((array)$old['_attachments'] as $cid => $oldatt) {
if ($attachment['id'] == $oldatt['id'])
$key = $cid;
}
}
// flagged for deletion => set to false
if ($attachment['_deleted'] || in_array($attachment['id'], (array)$event['deleted_attachments'])) {
$event['_attachments'][$key] = false;
}
// replace existing entry
else if ($key) {
$event['_attachments'][$key] = $attachment;
}
// append as new attachment
else {
$event['_attachments'][] = $attachment;
}
}
$event['_attachments'] = array_merge((array)$old['_attachments'], $event['_attachments']);
// attachments flagged for deletion => set to false
foreach ($event['_attachments'] as $key => $attachment) {
if ($attachment['_deleted'] || in_array($attachment['id'], (array)$event['deleted_attachments'])) {
$event['_attachments'][$key] = false;
}
}
}
kolab_format::merge_attachments($event, $old);
return $event;
}

View file

@ -704,4 +704,68 @@ abstract class kolab_format
$this->obj->setAttachments($vattach);
}
}
/**
* Unified way of updating/deleting attachments of edited object
*
* @param array $object Kolab object data
* @param array $old Old version of Kolab object
*/
public static function merge_attachments(&$object, $old)
{
$object['_attachments'] = (array) $old['_attachments'];
// delete existing attachment(s)
if (!empty($object['deleted_attachments'])) {
foreach ($object['_attachments'] as $idx => $att) {
if ($object['deleted_attachments'] === true || in_array($att['id'], $object['deleted_attachments'])) {
$object['_attachments'][$idx] = false;
}
}
}
// in kolab_storage attachments are indexed by content-id
foreach ((array) $object['attachments'] as $attachment) {
$key = null;
// Roundcube ID has nothing to do with the storage ID, remove it
// for uploaded/new attachments
// FIXME: Roundcube uses 'data', kolab_format uses 'content'
if ($attachment['content'] || $attachment['path'] || $attachment['data']) {
unset($attachment['id']);
}
if ($attachment['id']) {
foreach ((array) $object['_attachments'] as $cid => $att) {
if ($att && $attachment['id'] == $att['id']) {
$key = $cid;
}
}
}
else {
// find attachment by name, so we can update it if exists
// and make sure there are no duplicates
foreach ((array) $object['_attachments'] as $cid => $att) {
if ($att && $attachment['name'] == $att['name']) {
$key = $cid;
}
}
}
if ($key && $attachment['_deleted']) {
$object['_attachments'][$key] = false;
}
// replace existing entry
else if ($key) {
$object['_attachments'][$key] = $attachment;
}
// append as new attachment
else {
$object['_attachments'][] = $attachment;
}
}
unset($object['attachments']);
unset($object['deleted_attachments']);
}
}

View file

@ -1308,46 +1308,8 @@ class tasklist_kolab_driver extends tasklist_driver
$object['recurrence'] = $old['recurrence'];
}
// delete existing attachment(s)
if (!empty($task['deleted_attachments'])) {
foreach ($task['deleted_attachments'] as $attachment) {
if (is_array($object['_attachments'])) {
foreach ($object['_attachments'] as $idx => $att) {
if ($att['id'] == $attachment)
$object['_attachments'][$idx] = false;
}
}
}
unset($task['deleted_attachments']);
}
// in kolab_storage attachments are indexed by content-id
if (is_array($task['attachments'])) {
foreach ($task['attachments'] as $idx => $attachment) {
$key = null;
// Roundcube ID has nothing to do with the storage ID, remove it
if ($attachment['content'] || $attachment['path']) {
unset($attachment['id']);
}
else {
foreach ((array)$old['_attachments'] as $cid => $oldatt) {
if ($oldatt && $attachment['id'] == $oldatt['id'])
$key = $cid;
}
}
// replace existing entry
if ($key) {
$object['_attachments'][$key] = $attachment;
}
// append as new attachment
else {
$object['_attachments'][] = $attachment;
}
}
unset($object['attachments']);
}
unset($task['attachments']);
kolab_format::merge_attachments($object, $old);
// allow sequence increments if I'm the organizer
if ($this->plugin->is_organizer($object) && empty($object['_method'])) {

View file

@ -2088,6 +2088,15 @@ class tasklist extends rcube_plugin
if ($task['_method'] == 'CANCEL') {
$task['status'] = 'CANCELLED';
}
// update attachments list, allow attachments update only on REQUEST (#5342)
if ($task['_method'] == 'REQUEST') {
$task['deleted_attachments'] = true;
}
else {
unset($task['attachments']);
}
// show me as free when declined (#1670)
if ($status == 'declined' || $task['status'] == 'CANCELLED') {
$task['free_busy'] = 'free';