Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/dav/appinfo/v1/caldav.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
$config,
Server::get(\OCA\DAV\CalDAV\Sharing\Backend::class),
Server::get(FederatedCalendarMapper::class),
Server::get(\OCP\ICacheFactory::class),
true
);

Expand Down
61 changes: 57 additions & 4 deletions apps/dav/lib/CalDAV/CalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
use OCP\DB\Exception;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
Expand Down Expand Up @@ -202,6 +204,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
private string $dbObjectInvitationsTable = 'calendar_invitations';
private array $cachedObjects = [];

private readonly ICache $publishStatusCache;

public function __construct(
private IDBConnection $db,
private Principal $principalBackend,
Expand All @@ -212,8 +216,10 @@ public function __construct(
private IConfig $config,
private Sharing\Backend $calendarSharingBackend,
private FederatedCalendarMapper $federatedCalendarMapper,
ICacheFactory $cacheFactory,
private bool $legacyEndpoint = false,
) {
$this->publishStatusCache = $cacheFactory->createInMemory();
}

/**
Expand Down Expand Up @@ -923,6 +929,8 @@ public function updateCalendar($calendarId, PropPatch $propPatch) {
* @return void
*/
public function deleteCalendar($calendarId, bool $forceDeletePermanently = false) {
$this->publishStatusCache->remove((string)$calendarId);

$this->atomic(function () use ($calendarId, $forceDeletePermanently): void {
// The calendar is deleted right away if this is either enforced by the caller
// or the special contacts birthday calendar or when the preference of an empty
Expand Down Expand Up @@ -3221,7 +3229,7 @@ public function preloadShares(array $resourceIds): void {
* @return string|null
*/
public function setPublishStatus($value, $calendar) {
return $this->atomic(function () use ($value, $calendar) {
$publishStatus = $this->atomic(function () use ($value, $calendar) {
$calendarId = $calendar->getResourceId();
$calendarData = $this->getCalendarById($calendarId);

Expand Down Expand Up @@ -3249,23 +3257,68 @@ public function setPublishStatus($value, $calendar) {
$this->dispatcher->dispatchTyped(new CalendarUnpublishedEvent($calendarId, $calendarData));
return null;
}, $this->db);

$this->publishStatusCache->set((string)$calendar->getResourceId(), $publishStatus ?? false);
return $publishStatus;
}

/**
* @param Calendar $calendar
* @return mixed
* @return string|false
*/
public function getPublishStatus($calendar) {
$cached = $this->publishStatusCache->get((string)$calendar->getResourceId());
if ($cached !== null) {
return $cached;
}

$query = $this->db->getQueryBuilder();
$result = $query->select('publicuri')
->from('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($calendar->getResourceId())))
->andWhere($query->expr()->eq('access', $query->createNamedParameter(self::ACCESS_PUBLIC)))
->executeQuery();

$row = $result->fetch();
$publishStatus = $result->fetchOne();
$result->closeCursor();

$this->publishStatusCache->set((string)$calendar->getResourceId(), $publishStatus);
return $publishStatus;
}

/**
* @param int[] $resourceIds
*/
public function preloadPublishStatuses(array $resourceIds): void {
$query = $this->db->getQueryBuilder();
$result = $query->select('resourceid', 'publicuri')
->from('dav_shares')
->where($query->expr()->in(
'resourceid',
$query->createNamedParameter($resourceIds, IQueryBuilder::PARAM_INT_ARRAY),
IQueryBuilder::PARAM_INT_ARRAY,
))
->andWhere($query->expr()->eq(
'access',
$query->createNamedParameter(self::ACCESS_PUBLIC, IQueryBuilder::PARAM_INT),
IQueryBuilder::PARAM_INT,
))
->executeQuery();

$hasPublishStatuses = [];
while ($row = $result->fetch()) {
$this->publishStatusCache->set((string)$row['resourceid'], $row['publicuri']);
$hasPublishStatuses[(int)$row['resourceid']] = true;
}

// Also remember resources with no publish status
foreach ($resourceIds as $resourceId) {
if (!isset($hasPublishStatuses[$resourceId])) {
$this->publishStatusCache->set((string)$resourceId, false);
}
}

$result->closeCursor();
return $row ? reset($row) : false;
}

/**
Expand Down
16 changes: 16 additions & 0 deletions apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/
namespace OCA\DAV\CalDAV\Publishing;

use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\Publishing\Xml\Publisher;
use OCP\AppFramework\Http;
use OCP\IConfig;
Expand Down Expand Up @@ -91,6 +93,20 @@ public function initialize(Server $server) {
}

public function propFind(PropFind $propFind, INode $node) {
if ($node instanceof CalendarHome && $propFind->getDepth() === 1) {
$backend = $node->getCalDAVBackend();
if ($backend instanceof CalDavBackend) {
$calendars = array_filter(
$node->getChildren(),
static fn ($child) => $child instanceof Calendar,
);
$resourceIds = array_map(
static fn (Calendar $calendar) => $calendar->getResourceId(),
$calendars,
);
$backend->preloadPublishStatuses($resourceIds);
}
}
if ($node instanceof Calendar) {
$propFind->handle('{' . self::NS_CALENDARSERVER . '}publish-url', function () use ($node) {
if ($node->getPublishStatus()) {
Expand Down
2 changes: 2 additions & 0 deletions apps/dav/lib/Command/CreateCalendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
Expand Down Expand Up @@ -82,6 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$config,
Server::get(Backend::class),
Server::get(FederatedCalendarMapper::class),
Server::get(ICacheFactory::class),
);
$caldav->createCalendar("principals/users/$user", $name, []);
return self::SUCCESS;
Expand Down
2 changes: 2 additions & 0 deletions apps/dav/lib/RootCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
Expand Down Expand Up @@ -108,6 +109,7 @@ public function __construct() {
$config,
$calendarSharingBackend,
Server::get(FederatedCalendarMapper::class),
Server::get(ICacheFactory::class),
false,
);
$userCalendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users', $logger, $l10n, $config, $federatedCalendarFactory);
Expand Down
4 changes: 4 additions & 0 deletions apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ abstract class AbstractCalDavBackend extends TestCase {
protected RemoteUserPrincipalBackend&MockObject $remoteUserPrincipalBackend;
protected FederationSharingService&MockObject $federationSharingService;
protected FederatedCalendarMapper&MockObject $federatedCalendarMapper;
protected ICacheFactory $cacheFactory;

public const UNIT_TEST_USER = 'principals/users/caldav-unit-test';
public const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1';
public const UNIT_TEST_GROUP = 'principals/groups/caldav-unit-test-group';
Expand Down Expand Up @@ -110,6 +112,7 @@ protected function setUp(): void {
new Service(new SharingMapper($this->db)),
$this->federationSharingService,
$this->logger);
$this->cacheFactory = $this->createMock(ICacheFactory::class);
$this->backend = new CalDavBackend(
$this->db,
$this->principal,
Expand All @@ -120,6 +123,7 @@ protected function setUp(): void {
$this->config,
$this->sharingBackend,
$this->federatedCalendarMapper,
$this->cacheFactory,
false,
);

Expand Down
4 changes: 4 additions & 0 deletions apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\DAV\CalDAV\PublicCalendarRoot;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
Expand Down Expand Up @@ -43,6 +44,7 @@ class PublicCalendarRootTest extends TestCase {
protected IConfig&MockObject $config;
private ISecureRandom $random;
private LoggerInterface&MockObject $logger;
protected ICacheFactory&MockObject $cacheFactory;

protected FederatedCalendarMapper&MockObject $federatedCalendarMapper;

Expand All @@ -56,6 +58,7 @@ protected function setUp(): void {
$this->random = Server::get(ISecureRandom::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->federatedCalendarMapper = $this->createMock(FederatedCalendarMapper::class);
$this->cacheFactory = $this->createMock(ICacheFactory::class);
$dispatcher = $this->createMock(IEventDispatcher::class);
$config = $this->createMock(IConfig::class);
$sharingBackend = $this->createMock(\OCA\DAV\CalDAV\Sharing\Backend::class);
Expand All @@ -78,6 +81,7 @@ protected function setUp(): void {
$config,
$sharingBackend,
$this->federatedCalendarMapper,
$this->cacheFactory,
false,
);
$this->l10n = $this->createMock(IL10N::class);
Expand Down
Loading