Skip to content

Commit

Permalink
Merge pull request #30438 from nextcloud/fix/caldav-trash-bin-deleted…
Browse files Browse the repository at this point in the history
…-at-int

Fix column/property types in CalDAV
  • Loading branch information
ChristophWurst authored Apr 1, 2022
2 parents d3d5349 + 288f07a commit 5f2afad
Showing 1 changed file with 79 additions and 72 deletions.
151 changes: 79 additions & 72 deletions apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@
use Sabre\VObject\Recur\EventIterator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use function array_column;
use function array_merge;
use function array_values;
use function explode;
use function is_array;
use function is_resource;
use function pathinfo;
use function rewind;
use function settype;
use function sprintf;
use function str_replace;
use function strtolower;
Expand Down Expand Up @@ -142,20 +144,19 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public const CLASSIFICATION_CONFIDENTIAL = 2;

/**
* List of CalDAV properties, and how they map to database field names
* List of CalDAV properties, and how they map to database field names and their type
* Add your own properties by simply adding on to this array.
*
* Note that only string-based properties are supported here.
*
* @var array
* @psalm-var array<string, string[]>
*/
public $propertyMap = [
'{DAV:}displayname' => 'displayname',
'{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => 'deleted_at',
'{DAV:}displayname' => ['displayname', 'string'],
'{urn:ietf:params:xml:ns:caldav}calendar-description' => ['description', 'string'],
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => ['timezone', 'string'],
'{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'],
'{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => ['deleted_at', 'int'],
];

/**
Expand All @@ -164,13 +165,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @var array
*/
public $subscriptionPropertyMap = [
'{DAV:}displayname' => 'displayname',
'{http://apple.com/ns/ical/}refreshrate' => 'refreshrate',
'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
'{http://calendarserver.org/ns/}subscribed-strip-todos' => 'striptodos',
'{http://calendarserver.org/ns/}subscribed-strip-alarms' => 'stripalarms',
'{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments',
'{DAV:}displayname' => ['displayname', 'string'],
'{http://apple.com/ns/ical/}refreshrate' => ['refreshrate', 'string'],
'{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'],
'{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'],
'{http://calendarserver.org/ns/}subscribed-strip-todos' => ['striptodos', 'bool'],
'{http://calendarserver.org/ns/}subscribed-strip-alarms' => ['stripalarms', 'string'],
'{http://calendarserver.org/ns/}subscribed-strip-attachments' => ['stripattachments', 'string'],
];

/**
Expand Down Expand Up @@ -351,7 +352,7 @@ public function getDeletedCalendars(int $deletedBefore): array {
public function getCalendarsForUser($principalUri) {
$principalUriOriginal = $principalUri;
$principalUri = $this->convertPrincipal($principalUri, true);
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
Expand Down Expand Up @@ -392,10 +393,7 @@ public function getCalendarsForUser($principalUri) {
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $this->convertPrincipal($principalUri, !$this->legacyEndpoint),
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -411,7 +409,7 @@ public function getCalendarsForUser($principalUri) {

$principals[] = $principalUri;

$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
Expand Down Expand Up @@ -469,10 +467,7 @@ public function getCalendarsForUser($principalUri) {
$readOnlyPropertyName => $readOnly,
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -489,7 +484,7 @@ public function getCalendarsForUser($principalUri) {
*/
public function getUsersOwnCalendars($principalUri) {
$principalUri = $this->convertPrincipal($principalUri, true);
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
Expand Down Expand Up @@ -518,10 +513,8 @@ public function getUsersOwnCalendars($principalUri) {
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];
foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand Down Expand Up @@ -556,7 +549,7 @@ private function getUserDisplayName($uid) {
* @return array
*/
public function getPublicCalendars() {
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
Expand Down Expand Up @@ -595,10 +588,7 @@ public function getPublicCalendars() {
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -617,7 +607,7 @@ public function getPublicCalendars() {
* @throws NotFound
*/
public function getPublicCalendar($uri) {
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
Expand Down Expand Up @@ -663,10 +653,7 @@ public function getPublicCalendar($uri) {
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -679,7 +666,7 @@ public function getPublicCalendar($uri) {
* @return array|null
*/
public function getCalendarByUri($principal, $uri) {
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
Expand Down Expand Up @@ -717,10 +704,7 @@ public function getCalendarByUri($principal, $uri) {
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -732,7 +716,7 @@ public function getCalendarByUri($principal, $uri) {
* @return array|null
*/
public function getCalendarById($calendarId) {
$fields = array_values($this->propertyMap);
$fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
Expand Down Expand Up @@ -769,10 +753,7 @@ public function getCalendarById($calendarId) {
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];

foreach ($this->propertyMap as $xmlName => $dbName) {
$calendar[$xmlName] = $row[$dbName];
}

$calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);

Expand All @@ -783,7 +764,7 @@ public function getCalendarById($calendarId) {
* @param $subscriptionId
*/
public function getSubscriptionById($subscriptionId) {
$fields = array_values($this->subscriptionPropertyMap);
$fields = array_column($this->subscriptionPropertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'source';
Expand Down Expand Up @@ -815,13 +796,7 @@ public function getSubscriptionById($subscriptionId) {
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
];

foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
if (!is_null($row[$dbName])) {
$subscription[$xmlName] = $row[$dbName];
}
}

return $subscription;
return $this->rowToSubscription($row, $subscription);
}

/**
Expand Down Expand Up @@ -863,7 +838,7 @@ public function createCalendar($principalUri, $calendarUri, array $properties) {
$values['transparent'] = (int) ($properties[$transp]->getValue() === 'transparent');
}

foreach ($this->propertyMap as $xmlName => $dbName) {
foreach ($this->propertyMap as $xmlName => [$dbName, $type]) {
if (isset($properties[$xmlName])) {
$values[$dbName] = $properties[$xmlName];
}
Expand Down Expand Up @@ -912,7 +887,7 @@ public function updateCalendar($calendarId, PropPatch $propPatch) {
$newValues[$fieldName] = (int) ($propertyValue->getValue() === 'transparent');
break;
default:
$fieldName = $this->propertyMap[$propertyName];
$fieldName = $this->propertyMap[$propertyName][0];
$newValues[$fieldName] = $propertyValue;
break;
}
Expand Down Expand Up @@ -1109,7 +1084,7 @@ public function getDeletedCalendarObjects(int $deletedBefore): array {
'size' => (int) $row['size'],
'component' => strtolower($row['componenttype']),
'classification' => (int) $row['classification'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'],
];
}
$stmt->closeCursor();
Expand Down Expand Up @@ -1148,7 +1123,7 @@ public function getDeletedCalendarObjectsByPrincipal(string $principalUri): arra
'size' => (int)$row['size'],
'component' => strtolower($row['componenttype']),
'classification' => (int)$row['classification'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'],
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'],
];
}
$stmt->closeCursor();
Expand Down Expand Up @@ -2452,7 +2427,7 @@ public function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limi
* @return array
*/
public function getSubscriptionsForUser($principalUri) {
$fields = array_values($this->subscriptionPropertyMap);
$fields = array_column($this->subscriptionPropertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'source';
Expand Down Expand Up @@ -2480,13 +2455,7 @@ public function getSubscriptionsForUser($principalUri) {
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
];

foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
if (!is_null($row[$dbName])) {
$subscription[$xmlName] = $row[$dbName];
}
}

$subscriptions[] = $subscription;
$subscriptions[] = $this->rowToSubscription($row, $subscription);
}

return $subscriptions;
Expand Down Expand Up @@ -2517,7 +2486,7 @@ public function createSubscription($principalUri, $uri, array $properties) {

$propertiesBoolean = ['striptodos', 'stripalarms', 'stripattachments'];

foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) {
if (array_key_exists($xmlName, $properties)) {
$values[$dbName] = $properties[$xmlName];
if (in_array($dbName, $propertiesBoolean)) {
Expand Down Expand Up @@ -2579,7 +2548,7 @@ public function updateSubscription($subscriptionId, PropPatch $propPatch) {
if ($propertyName === '{http://calendarserver.org/ns/}source') {
$newValues['source'] = $propertyValue->getHref();
} else {
$fieldName = $this->subscriptionPropertyMap[$propertyName];
$fieldName = $this->subscriptionPropertyMap[$propertyName][0];
$newValues[$fieldName] = $propertyValue;
}
}
Expand Down Expand Up @@ -3263,4 +3232,42 @@ private function addResourceTypeToCalendar(array $row, array $calendar): array {
}
return $calendar;
}

/**
* Amend the calendar info with database row data
*
* @param array $row
* @param array $calendar
*
* @return array
*/
private function rowToCalendar($row, array $calendar): array {
foreach ($this->propertyMap as $xmlName => [$dbName, $type]) {
$value = $row[$dbName];
if ($value !== null) {
settype($value, $type);
}
$calendar[$xmlName] = $value;
}
return $calendar;
}

/**
* Amend the subscription info with database row data
*
* @param array $row
* @param array $subscription
*
* @return array
*/
private function rowToSubscription($row, array $subscription): array {
foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) {
$value = $row[$dbName];
if ($value !== null) {
settype($value, $type);
}
$subscription[$xmlName] = $value;
}
return $subscription;
}
}

0 comments on commit 5f2afad

Please sign in to comment.