Skip to content

Commit e210043

Browse files
committed
feat(caldav): expose calendar subscriptions
Signed-off-by: Daniel Kesselberg <[email protected]>
1 parent 6fc2c47 commit e210043

18 files changed

+585
-29
lines changed

apps/dav/composer/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@
4646
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => $baseDir . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
4747
'OCA\\DAV\\CalDAV\\BirthdayService' => $baseDir . '/../lib/CalDAV/BirthdayService.php',
4848
'OCA\\DAV\\CalDAV\\CachedSubscription' => $baseDir . '/../lib/CalDAV/CachedSubscription.php',
49+
'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => $baseDir . '/../lib/CalDAV/CachedSubscriptionImpl.php',
4950
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => $baseDir . '/../lib/CalDAV/CachedSubscriptionObject.php',
51+
'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => $baseDir . '/../lib/CalDAV/CachedSubscriptionProvider.php',
5052
'OCA\\DAV\\CalDAV\\CalDavBackend' => $baseDir . '/../lib/CalDAV/CalDavBackend.php',
5153
'OCA\\DAV\\CalDAV\\Calendar' => $baseDir . '/../lib/CalDAV/Calendar.php',
5254
'OCA\\DAV\\CalDAV\\CalendarHome' => $baseDir . '/../lib/CalDAV/CalendarHome.php',

apps/dav/composer/composer/autoload_static.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ class ComposerStaticInitDAV
6161
'OCA\\DAV\\CalDAV\\BirthdayCalendar\\EnablePlugin' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayCalendar/EnablePlugin.php',
6262
'OCA\\DAV\\CalDAV\\BirthdayService' => __DIR__ . '/..' . '/../lib/CalDAV/BirthdayService.php',
6363
'OCA\\DAV\\CalDAV\\CachedSubscription' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscription.php',
64+
'OCA\\DAV\\CalDAV\\CachedSubscriptionImpl' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionImpl.php',
6465
'OCA\\DAV\\CalDAV\\CachedSubscriptionObject' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionObject.php',
66+
'OCA\\DAV\\CalDAV\\CachedSubscriptionProvider' => __DIR__ . '/..' . '/../lib/CalDAV/CachedSubscriptionProvider.php',
6567
'OCA\\DAV\\CalDAV\\CalDavBackend' => __DIR__ . '/..' . '/../lib/CalDAV/CalDavBackend.php',
6668
'OCA\\DAV\\CalDAV\\Calendar' => __DIR__ . '/..' . '/../lib/CalDAV/Calendar.php',
6769
'OCA\\DAV\\CalDAV\\CalendarHome' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarHome.php',

apps/dav/lib/AppInfo/Application.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
use OCA\DAV\CalDAV\Activity\Backend;
3636
use OCA\DAV\CalDAV\AppCalendar\AppCalendarPlugin;
37+
use OCA\DAV\CalDAV\CachedSubscriptionProvider;
3738
use OCA\DAV\CalDAV\CalendarManager;
3839
use OCA\DAV\CalDAV\CalendarProvider;
3940
use OCA\DAV\CalDAV\Reminder\NotificationProvider\AudioProvider;
@@ -207,6 +208,7 @@ public function register(IRegistrationContext $context): void {
207208
$context->registerNotifierService(Notifier::class);
208209

209210
$context->registerCalendarProvider(CalendarProvider::class);
211+
$context->registerCalendarProvider(CachedSubscriptionProvider::class);
210212

211213
$context->registerUserMigrator(CalendarMigrator::class);
212214
$context->registerUserMigrator(ContactsMigrator::class);

apps/dav/lib/CalDAV/AppCalendar/AppCalendarPlugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ protected function getWrappedCalendars(string $principalUri, array $calendarUris
6868
return array_values(
6969
array_filter($this->manager->getCalendarsForPrincipal($principalUri, $calendarUris), function ($c) {
7070
// We must not provide a wrapper for DAV calendars
71-
return ! ($c instanceof \OCA\DAV\CalDAV\CalendarImpl);
71+
return ! (($c instanceof \OCA\DAV\CalDAV\CalendarImpl) || ($c instanceof \OCA\DAV\CalDAV\CachedSubscriptionImpl));
7272
})
7373
);
7474
}

apps/dav/lib/CalDAV/CachedSubscription.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ public function getACL() {
7373
'principal' => '{DAV:}authenticated',
7474
'protected' => true,
7575
],
76+
[
77+
'privilege' => '{DAV:}write-properties',
78+
'principal' => $this->getOwner(),
79+
'protected' => true,
80+
]
7681
];
7782
}
7883

@@ -97,7 +102,6 @@ public function getChildACL() {
97102
'principal' => $this->getOwner() . '/calendar-proxy-read',
98103
'protected' => true,
99104
],
100-
101105
];
102106
}
103107

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright 2024 Daniel Kesselberg <[email protected]>
7+
*
8+
* @author Daniel Kesselberg <[email protected]>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
namespace OCA\DAV\CalDAV;
27+
28+
use OCP\Calendar\ICalendar;
29+
use OCP\Constants;
30+
31+
class CachedSubscriptionImpl implements ICalendar {
32+
private CalDavBackend $backend;
33+
private CachedSubscription $calendar;
34+
/** @var array<string, mixed> */
35+
private array $calendarInfo;
36+
37+
public function __construct(
38+
CachedSubscription $calendar,
39+
array $calendarInfo,
40+
CalDavBackend $backend
41+
) {
42+
$this->calendar = $calendar;
43+
$this->calendarInfo = $calendarInfo;
44+
$this->backend = $backend;
45+
}
46+
47+
/**
48+
* @return string defining the technical unique key
49+
* @since 13.0.0
50+
*/
51+
public function getKey(): string {
52+
return (string) $this->calendarInfo['id'];
53+
}
54+
55+
/**
56+
* {@inheritDoc}
57+
*/
58+
public function getUri(): string {
59+
return $this->calendarInfo['uri'];
60+
}
61+
62+
/**
63+
* In comparison to getKey() this function returns a human readable (maybe translated) name
64+
* @since 13.0.0
65+
*/
66+
public function getDisplayName(): ?string {
67+
return $this->calendarInfo['{DAV:}displayname'];
68+
}
69+
70+
/**
71+
* Calendar color
72+
* @since 13.0.0
73+
*/
74+
public function getDisplayColor(): ?string {
75+
return $this->calendarInfo['{http://apple.com/ns/ical/}calendar-color'];
76+
}
77+
78+
/**
79+
* @param string $pattern which should match within the $searchProperties
80+
* @param array $searchProperties defines the properties within the query pattern should match
81+
* @param array $options - optional parameters:
82+
* ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
83+
* @param int|null $limit - limit number of search results
84+
* @param int|null $offset - offset for paging of search results
85+
* @return array an array of events/journals/todos which are arrays of key-value-pairs
86+
* @since 13.0.0
87+
*/
88+
public function search(string $pattern, array $searchProperties = [], array $options = [], $limit = null, $offset = null): array {
89+
return $this->backend->search($this->calendarInfo, $pattern, $searchProperties, $options, $limit, $offset);
90+
}
91+
92+
/**
93+
* @return int build up using \OCP\Constants
94+
* @since 13.0.0
95+
*/
96+
public function getPermissions(): int {
97+
$permissions = $this->calendar->getACL();
98+
$result = 0;
99+
foreach ($permissions as $permission) {
100+
switch ($permission['privilege']) {
101+
case '{DAV:}read':
102+
$result |= Constants::PERMISSION_READ;
103+
break;
104+
}
105+
}
106+
107+
return $result;
108+
}
109+
110+
public function isDeleted(): bool {
111+
return false;
112+
}
113+
114+
public function getSource(): string {
115+
return $this->calendarInfo['source'];
116+
}
117+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright 2024 Daniel Kesselberg <[email protected]>
7+
*
8+
* @author Daniel Kesselberg <[email protected]>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
namespace OCA\DAV\CalDAV;
27+
28+
use OCP\Calendar\ICalendarProvider;
29+
30+
class CachedSubscriptionProvider implements ICalendarProvider {
31+
32+
public function __construct(
33+
private CalDavBackend $calDavBackend
34+
) {
35+
}
36+
37+
public function getCalendars(string $principalUri, array $calendarUris = []): array {
38+
$calendarInfos = $this->calDavBackend->getSubscriptionsForUser($principalUri);
39+
40+
if (count($calendarUris) > 0) {
41+
$calendarInfos = array_filter($calendarInfos, fn (array $subscription) => in_array($subscription['uri'], $calendarUris));
42+
}
43+
44+
$calendarInfos = array_values(array_filter($calendarInfos));
45+
46+
$iCalendars = [];
47+
foreach ($calendarInfos as $calendarInfo) {
48+
$calendar = new CachedSubscription($this->calDavBackend, $calendarInfo);
49+
$iCalendars[] = new CachedSubscriptionImpl(
50+
$calendar,
51+
$calendarInfo,
52+
$this->calDavBackend,
53+
);
54+
}
55+
return $iCalendars;
56+
}
57+
}

apps/dav/lib/CalDAV/CalDavBackend.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1882,12 +1882,18 @@ public function search(
18821882
$outerQuery = $this->db->getQueryBuilder();
18831883
$innerQuery = $this->db->getQueryBuilder();
18841884

1885+
if (isset($calendarInfo['source'])) {
1886+
$calendarType = self::CALENDAR_TYPE_SUBSCRIPTION;
1887+
} else {
1888+
$calendarType = self::CALENDAR_TYPE_CALENDAR;
1889+
}
1890+
18851891
$innerQuery->selectDistinct('op.objectid')
18861892
->from($this->dbObjectPropertiesTable, 'op')
18871893
->andWhere($innerQuery->expr()->eq('op.calendarid',
18881894
$outerQuery->createNamedParameter($calendarInfo['id'])))
18891895
->andWhere($innerQuery->expr()->eq('op.calendartype',
1890-
$outerQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)));
1896+
$outerQuery->createNamedParameter($calendarType)));
18911897

18921898
$outerQuery->select('c.id', 'c.calendardata', 'c.componenttype', 'c.uid', 'c.uri')
18931899
->from('calendarobjects', 'c')

apps/dav/lib/CalDAV/CalendarHome.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,16 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome {
5353
/** @var PluginManager */
5454
private $pluginManager;
5555

56-
/** @var bool */
57-
private $returnCachedSubscriptions = false;
58-
5956
/** @var LoggerInterface */
6057
private $logger;
6158
private ?array $cachedChildren = null;
6259

63-
public function __construct(BackendInterface $caldavBackend, $principalInfo, LoggerInterface $logger) {
60+
public function __construct(
61+
BackendInterface $caldavBackend,
62+
array $principalInfo,
63+
LoggerInterface $logger,
64+
private bool $returnCachedSubscriptions
65+
) {
6466
parent::__construct($caldavBackend, $principalInfo);
6567
$this->l10n = \OC::$server->getL10N('dav');
6668
$this->config = \OC::$server->getConfig();
@@ -219,8 +221,4 @@ public function calendarSearch(array $filters, $limit = null, $offset = null) {
219221
$principalUri = $this->principalInfo['uri'];
220222
return $this->caldavBackend->calendarSearch($principalUri, $filters, $limit, $offset);
221223
}
222-
223-
public function enableCachedSubscriptionsForThisRequest() {
224-
$this->returnCachedSubscriptions = true;
225-
}
226224
}

apps/dav/lib/CalDAV/CalendarRoot.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
3333
private LoggerInterface $logger;
3434

35+
private array $returnCachedSubscriptions = [];
36+
3537
public function __construct(
3638
PrincipalBackend\BackendInterface $principalBackend,
3739
Backend\BackendInterface $caldavBackend,
@@ -43,7 +45,12 @@ public function __construct(
4345
}
4446

4547
public function getChildForPrincipal(array $principal) {
46-
return new CalendarHome($this->caldavBackend, $principal, $this->logger);
48+
return new CalendarHome(
49+
$this->caldavBackend,
50+
$principal,
51+
$this->logger,
52+
array_key_exists($principal['uri'], $this->returnCachedSubscriptions)
53+
);
4754
}
4855

4956
public function getName() {
@@ -56,4 +63,8 @@ public function getName() {
5663

5764
return parent::getName();
5865
}
66+
67+
public function enableReturnCachedSubscriptions(string $principalUri): void {
68+
$this->returnCachedSubscriptions['principals/users/' . $principalUri] = true;
69+
}
5970
}

0 commit comments

Comments
 (0)