Skip to content

Commit

Permalink
Move calendar objects between calendars instead of deleting and recre…
Browse files Browse the repository at this point in the history
…ating them

Signed-off-by: Anna Larch <[email protected]>
  • Loading branch information
miaulalala committed Dec 10, 2021
1 parent d851e58 commit c605aa0
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 7 deletions.
46 changes: 45 additions & 1 deletion apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
use OCA\DAV\Events\SubscriptionCreatedEvent;
use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCA\DAV\Events\SubscriptionUpdatedEvent;
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
Expand Down Expand Up @@ -1120,7 +1121,7 @@ public function getDeletedCalendarObjects(int $deletedBefore): array {
*
* @param string $principalUri
* @return array
* @throws \OCP\DB\Exception
* @throws Exception
*/
public function getDeletedCalendarObjectsByPrincipal(string $principalUri): array {
$query = $this->db->getQueryBuilder();
Expand Down Expand Up @@ -1413,6 +1414,49 @@ public function updateCalendarObject($calendarId, $objectUri, $calendarData, $ca
return '"' . $extraData['etag'] . '"';
}

/**
* Moves a calendar object from calendar to calendar.
*
* @param int $sourceCalendarId
* @param int $targetCalendarId
* @param int $objectId
* @param string $principalUri
* @param int $calendarType
* @throws Exception
*/
public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId, int $objectId, string $principalUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool {
$object = $this->getCalendarObjectById($principalUri, $objectId);
if (empty($object)) {
return false;
}

$query = $this->db->getQueryBuilder();
$query->update('calendarobjects')
->set('calendarid', $query->createNamedParameter($targetCalendarId))
->where($query->expr()->eq('id', $query->createNamedParameter($objectId)))
->andWhere($query->expr()->eq('calendartype', $query->createNamedParameter($calendarType)))
->executeStatement();

$this->purgeProperties($sourceCalendarId, $objectId);
$this->updateProperties($targetCalendarId, $object['uri'], $object['calendardata'], $calendarType);

$this->addChange($sourceCalendarId, $object['uri'], 1, $calendarType);
$this->addChange($targetCalendarId, $object['uri'], 3, $calendarType);

$object = $this->getCalendarObjectById($principalUri, $objectId);
if (empty($object)) {
return false;
}

if ($calendarType === self::CALENDAR_TYPE_CALENDAR) {
$calendarRow = $this->getCalendarById($targetCalendarId);
$shares = $this->getShares($targetCalendarId);
$this->dispatcher->dispatchTyped(new CalendarObjectUpdatedEvent($targetCalendarId, $calendarRow, $shares, $object));
}
return true;
}


/**
* @param int $calendarObjectId
* @param int $classification
Expand Down
18 changes: 17 additions & 1 deletion apps/dav/lib/CalDAV/Calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
use OCA\DAV\CalDAV\Trashbin\Plugin as TrashbinPlugin;
use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\Exception\UnsupportedLimitOnInitialSyncException;
use OCP\DB\Exception;
use OCP\IConfig;
use OCP\IL10N;
use Sabre\CalDAV\Backend\BackendInterface;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\IMoveTarget;
use Sabre\DAV\INode;
use Sabre\DAV\PropPatch;

/**
Expand All @@ -46,7 +49,7 @@
* @package OCA\DAV\CalDAV
* @property CalDavBackend $caldavBackend
*/
class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable {
class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable, IMoveTarget {

/** @var IConfig */
private $config;
Expand Down Expand Up @@ -422,4 +425,17 @@ public function restore(): void {
public function disableTrashbin(): void {
$this->useTrashbin = false;
}

public function moveInto($targetName, $sourcePath, INode $sourceNode) {
if (!($sourceNode instanceof CalendarObject)) {
return false;
}

try {
$result = $this->caldavBackend->moveCalendarObject($sourceNode->getCalendarId(), (int)$this->calendarInfo['id'], $sourceNode->getId(), $sourceNode->getPrincipalUri());
} catch (Exception $e) {
return false;
}
return $result;
}
}
8 changes: 8 additions & 0 deletions apps/dav/lib/CalDAV/CalendarObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,12 @@ private function canWrite() {
}
return true;
}

public function getCalendarId(): int {
return (int)$this->objectData['calendarId'];
}

public function getPrincipalUri(): string {
return $this->objectData['principaluri'];
}
}
14 changes: 9 additions & 5 deletions apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead,
return vsprintf($text, $parameters);
});

$logger = $this->createMock(\Psr\Log\LoggerInterface::class);

$config = $this->createMock(IConfig::class);

$this->userManager->expects($this->any())
Expand All @@ -147,14 +149,14 @@ public function testCalendarSharing($userCanRead, $userCanWrite, $groupCanRead,
$calendarId = $this->createTestCalendar();
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertCount(1, $calendars);
$calendar = new Calendar($this->backend, $calendars[0], $l10n, $config);
$calendar = new Calendar($this->backend, $calendars[0], $l10n, $config, $logger);
$this->legacyDispatcher->expects($this->at(0))
->method('dispatch')
->with('\OCA\DAV\CalDAV\CalDavBackend::updateShares');
$this->backend->updateShares($calendar, $add, []);
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1);
$this->assertCount(1, $calendars);
$calendar = new Calendar($this->backend, $calendars[0], $l10n, $config);
$calendar = new Calendar($this->backend, $calendars[0], $l10n, $config, $logger);
$acl = $calendar->getACL();
$this->assertAcl(self::UNIT_TEST_USER, '{DAV:}read', $acl);
$this->assertAcl(self::UNIT_TEST_USER, '{DAV:}write', $acl);
Expand Down Expand Up @@ -500,8 +502,8 @@ public function testPublications() {
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l10n */
$l10n = $this->createMock(IL10N::class);
$config = $this->createMock(IConfig::class);

$calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config);
$logger = $this->createMock(\Psr\Log\LoggerInterface::class);
$calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config, $logger);
$calendar->setPublishStatus(true);
$this->assertNotEquals(false, $calendar->getPublishStatus());

Expand Down Expand Up @@ -1237,7 +1239,9 @@ public function testSearchPrincipal(): void {

$sharerCalendars = $this->backend->getCalendarsForUser($sharer);
$this->assertCount(1, $sharerCalendars);
$sharerCalendar = new Calendar($this->backend, $sharerCalendars[0], $l10n, $config);

$logger = $this->createMock(\Psr\Log\LoggerInterface::class);
$sharerCalendar = new Calendar($this->backend, $sharerCalendars[0], $l10n, $config, $logger);
$this->backend->updateShares($sharerCalendar, [
[
'href' => 'principal:' . $me,
Expand Down

0 comments on commit c605aa0

Please sign in to comment.