diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index d7e5c494042..284b683141c 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -103,6 +103,7 @@ 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; @@ -141,20 +142,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 */ 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', 'string'], + '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'], + '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => ['deleted_at', 'int'], ]; /** @@ -335,7 +335,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 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'; @@ -376,10 +376,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \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); @@ -395,7 +392,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $principals[] = $principalUri; - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'a.id'; $fields[] = 'a.uri'; $fields[] = 'a.synctoken'; @@ -453,10 +450,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $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); @@ -473,7 +467,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription */ 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'; @@ -502,10 +496,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . 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); @@ -540,7 +532,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @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'; @@ -579,10 +571,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \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); @@ -601,7 +590,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @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'; @@ -647,10 +636,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . \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); @@ -663,7 +649,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @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'; @@ -701,10 +687,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . 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); @@ -716,7 +699,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @return array|null */ public function getCalendarById($calendarId) { - $fields = array_values($this->propertyMap); + $fields = array_column($this->propertyMap, 0); $fields[] = 'id'; $fields[] = 'uri'; $fields[] = 'synctoken'; @@ -753,10 +736,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '{' . 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); @@ -847,7 +827,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $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]; } @@ -896,7 +876,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $newValues[$fieldName] = (int) ($propertyValue->getValue() === 'transparent'); break; default: - $fieldName = $this->propertyMap[$propertyName]; + $fieldName = $this->propertyMap[$propertyName][0]; $newValues[$fieldName] = $propertyValue; break; } @@ -1093,7 +1073,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '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(); @@ -1132,7 +1112,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription '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(); @@ -3197,4 +3177,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } 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; + } }