diff options
Diffstat (limited to 'apps/dav/lib/BackgroundJob')
15 files changed, 180 insertions, 532 deletions
diff --git a/apps/dav/lib/BackgroundJob/BuildReminderIndexBackgroundJob.php b/apps/dav/lib/BackgroundJob/BuildReminderIndexBackgroundJob.php index d908cd3ae82..1165367c33f 100644 --- a/apps/dav/lib/BackgroundJob/BuildReminderIndexBackgroundJob.php +++ b/apps/dav/lib/BackgroundJob/BuildReminderIndexBackgroundJob.php @@ -22,41 +22,28 @@ use Psr\Log\LoggerInterface; */ class BuildReminderIndexBackgroundJob extends QueuedJob { - /** @var IDBConnection */ - private $db; - - /** @var ReminderService */ - private $reminderService; - - private LoggerInterface $logger; - - /** @var IJobList */ - private $jobList; - /** @var ITimeFactory */ private $timeFactory; /** * BuildReminderIndexBackgroundJob constructor. */ - public function __construct(IDBConnection $db, - ReminderService $reminderService, - LoggerInterface $logger, - IJobList $jobList, - ITimeFactory $timeFactory) { + public function __construct( + private IDBConnection $db, + private ReminderService $reminderService, + private LoggerInterface $logger, + private IJobList $jobList, + ITimeFactory $timeFactory, + ) { parent::__construct($timeFactory); - $this->db = $db; - $this->reminderService = $reminderService; - $this->logger = $logger; - $this->jobList = $jobList; $this->timeFactory = $timeFactory; } public function run($argument) { - $offset = (int) $argument['offset']; - $stopAt = (int) $argument['stopAt']; + $offset = (int)$argument['offset']; + $stopAt = (int)$argument['stopAt']; - $this->logger->info('Building calendar reminder index (' . $offset .'/' . $stopAt . ')'); + $this->logger->info('Building calendar reminder index (' . $offset . '/' . $stopAt . ')'); $offset = $this->buildIndex($offset, $stopAt); @@ -88,7 +75,7 @@ class BuildReminderIndexBackgroundJob extends QueuedJob { $result = $query->executeQuery(); while ($row = $result->fetch(\PDO::FETCH_ASSOC)) { - $offset = (int) $row['id']; + $offset = (int)$row['id']; if (is_resource($row['calendardata'])) { $row['calendardata'] = stream_get_contents($row['calendardata']); } diff --git a/apps/dav/lib/BackgroundJob/CalendarRetentionJob.php b/apps/dav/lib/BackgroundJob/CalendarRetentionJob.php index 2de9c6d00ee..c6edac4f228 100644 --- a/apps/dav/lib/BackgroundJob/CalendarRetentionJob.php +++ b/apps/dav/lib/BackgroundJob/CalendarRetentionJob.php @@ -13,13 +13,11 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; class CalendarRetentionJob extends TimedJob { - /** @var RetentionService */ - private $service; - - public function __construct(ITimeFactory $time, - RetentionService $service) { + public function __construct( + ITimeFactory $time, + private RetentionService $service, + ) { parent::__construct($time); - $this->service = $service; // Run four times a day $this->setInterval(6 * 60 * 60); diff --git a/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php b/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php index 8895159d6ad..49b6b1607ef 100644 --- a/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php +++ b/apps/dav/lib/BackgroundJob/CleanupDirectLinksJob.php @@ -13,12 +13,11 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; class CleanupDirectLinksJob extends TimedJob { - /** @var DirectMapper */ - private $mapper; - - public function __construct(ITimeFactory $timeFactory, DirectMapper $mapper) { + public function __construct( + ITimeFactory $timeFactory, + private DirectMapper $mapper, + ) { parent::__construct($timeFactory); - $this->mapper = $mapper; // Run once a day at off-peak time $this->setInterval(24 * 60 * 60); diff --git a/apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php b/apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php index 1479cd363b3..7b664d03181 100644 --- a/apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php +++ b/apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php @@ -14,12 +14,11 @@ use OCP\IDBConnection; class CleanupInvitationTokenJob extends TimedJob { - /** @var IDBConnection */ - private $db; - - public function __construct(IDBConnection $db, ITimeFactory $time) { + public function __construct( + private IDBConnection $db, + ITimeFactory $time, + ) { parent::__construct($time); - $this->db = $db; // Run once a day at off-peak time $this->setInterval(24 * 60 * 60); diff --git a/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php b/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php new file mode 100644 index 00000000000..8a5e34381a7 --- /dev/null +++ b/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php @@ -0,0 +1,89 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\DAV\BackgroundJob; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\IJobList; +use OCP\BackgroundJob\QueuedJob; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IDBConnection; +use Psr\Log\LoggerInterface; + +class CleanupOrphanedChildrenJob extends QueuedJob { + public const ARGUMENT_CHILD_TABLE = 'childTable'; + public const ARGUMENT_PARENT_TABLE = 'parentTable'; + public const ARGUMENT_PARENT_ID = 'parentId'; + public const ARGUMENT_LOG_MESSAGE = 'logMessage'; + + private const BATCH_SIZE = 1000; + + public function __construct( + ITimeFactory $time, + private readonly IDBConnection $connection, + private readonly LoggerInterface $logger, + private readonly IJobList $jobList, + ) { + parent::__construct($time); + } + + protected function run($argument): void { + $childTable = $argument[self::ARGUMENT_CHILD_TABLE]; + $parentTable = $argument[self::ARGUMENT_PARENT_TABLE]; + $parentId = $argument[self::ARGUMENT_PARENT_ID]; + $logMessage = $argument[self::ARGUMENT_LOG_MESSAGE]; + + $orphanCount = $this->cleanUpOrphans($childTable, $parentTable, $parentId); + $this->logger->debug(sprintf($logMessage, $orphanCount)); + + // Requeue if there might be more orphans + if ($orphanCount >= self::BATCH_SIZE) { + $this->jobList->add(self::class, $argument); + } + } + + private function cleanUpOrphans( + string $childTable, + string $parentTable, + string $parentId, + ): int { + // We can't merge both queries into a single one here as DELETEing from a table while + // SELECTing it in a sub query is not supported by Oracle DB. + // Ref https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/delete.html#idm46006185488144 + + $selectQb = $this->connection->getQueryBuilder(); + + $selectQb->select('c.id') + ->from($childTable, 'c') + ->leftJoin('c', $parentTable, 'p', $selectQb->expr()->eq('c.' . $parentId, 'p.id')) + ->where($selectQb->expr()->isNull('p.id')) + ->setMaxResults(self::BATCH_SIZE); + + if (\in_array($parentTable, ['calendars', 'calendarsubscriptions'], true)) { + $calendarType = $parentTable === 'calendarsubscriptions' ? CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION : CalDavBackend::CALENDAR_TYPE_CALENDAR; + $selectQb->andWhere($selectQb->expr()->eq('c.calendartype', $selectQb->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); + } + + $result = $selectQb->executeQuery(); + $rows = $result->fetchAll(); + $result->closeCursor(); + if (empty($rows)) { + return 0; + } + + $orphanItems = array_map(static fn ($row) => $row['id'], $rows); + $deleteQb = $this->connection->getQueryBuilder(); + $deleteQb->delete($childTable) + ->where($deleteQb->expr()->in('id', $deleteQb->createNamedParameter($orphanItems, IQueryBuilder::PARAM_INT_ARRAY))); + $deleteQb->executeStatement(); + + return count($orphanItems); + } +} diff --git a/apps/dav/lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php b/apps/dav/lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php index fa53a8be4f0..bc306d58fe1 100644 --- a/apps/dav/lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php +++ b/apps/dav/lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php @@ -30,6 +30,6 @@ class DeleteOutdatedSchedulingObjects extends TimedJob { protected function run($argument): void { $time = $this->time->getTime() - (60 * 60); $this->calDavBackend->deleteOutdatedSchedulingObjects($time, 50000); - $this->logger->info("Removed outdated scheduling objects"); + $this->logger->info('Removed outdated scheduling objects'); } } diff --git a/apps/dav/lib/BackgroundJob/EventReminderJob.php b/apps/dav/lib/BackgroundJob/EventReminderJob.php index 5025919c84f..0e21e06fc35 100644 --- a/apps/dav/lib/BackgroundJob/EventReminderJob.php +++ b/apps/dav/lib/BackgroundJob/EventReminderJob.php @@ -8,6 +8,9 @@ declare(strict_types=1); */ namespace OCA\DAV\BackgroundJob; +use OC\User\NoUserException; +use OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException; +use OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException; use OCA\DAV\CalDAV\Reminder\ReminderService; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; @@ -15,18 +18,12 @@ use OCP\IConfig; class EventReminderJob extends TimedJob { - /** @var ReminderService */ - private $reminderService; - - /** @var IConfig */ - private $config; - - public function __construct(ITimeFactory $time, - ReminderService $reminderService, - IConfig $config) { + public function __construct( + ITimeFactory $time, + private ReminderService $reminderService, + private IConfig $config, + ) { parent::__construct($time); - $this->reminderService = $reminderService; - $this->config = $config; // Run every 5 minutes $this->setInterval(5 * 60); @@ -34,9 +31,9 @@ class EventReminderJob extends TimedJob { } /** - * @throws \OCA\DAV\CalDAV\Reminder\NotificationProvider\ProviderNotAvailableException - * @throws \OCA\DAV\CalDAV\Reminder\NotificationTypeDoesNotExistException - * @throws \OC\User\NoUserException + * @throws ProviderNotAvailableException + * @throws NotificationTypeDoesNotExistException + * @throws NoUserException */ public function run($argument):void { if ($this->config->getAppValue('dav', 'sendEventReminders', 'yes') !== 'yes') { diff --git a/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php b/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php index a6b0346908c..6d94f4810ed 100644 --- a/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php +++ b/apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php @@ -15,26 +15,19 @@ use OCP\IConfig; class GenerateBirthdayCalendarBackgroundJob extends QueuedJob { - /** @var BirthdayService */ - private $birthdayService; - - /** @var IConfig */ - private $config; - - public function __construct(ITimeFactory $time, - BirthdayService $birthdayService, - IConfig $config) { + public function __construct( + ITimeFactory $time, + private BirthdayService $birthdayService, + private IConfig $config, + ) { parent::__construct($time); - - $this->birthdayService = $birthdayService; - $this->config = $config; } public function run($argument) { $userId = $argument['userId']; $purgeBeforeGenerating = $argument['purgeBeforeGenerating'] ?? false; - // make sure admin didn't change his mind + // make sure admin didn't change their mind $isGloballyEnabled = $this->config->getAppValue('dav', 'generateBirthdayCalendar', 'yes'); if ($isGloballyEnabled !== 'yes') { return; diff --git a/apps/dav/lib/BackgroundJob/OutOfOfficeEventDispatcherJob.php b/apps/dav/lib/BackgroundJob/OutOfOfficeEventDispatcherJob.php index 8293b370996..cc4fd5dce9d 100644 --- a/apps/dav/lib/BackgroundJob/OutOfOfficeEventDispatcherJob.php +++ b/apps/dav/lib/BackgroundJob/OutOfOfficeEventDispatcherJob.php @@ -41,7 +41,7 @@ class OutOfOfficeEventDispatcherJob extends QueuedJob { try { $absence = $this->absenceMapper->findById($id); - } catch (DoesNotExistException | \OCP\DB\Exception $e) { + } catch (DoesNotExistException|\OCP\DB\Exception $e) { $this->logger->error('Failed to dispatch out-of-office event: ' . $e->getMessage(), [ 'exception' => $e, 'argument' => $argument, diff --git a/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php b/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php index 1ef33410f4f..8746588acc7 100644 --- a/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php +++ b/apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php @@ -18,24 +18,21 @@ use Psr\Log\LoggerInterface; class PruneOutdatedSyncTokensJob extends TimedJob { - private IConfig $config; - private LoggerInterface $logger; - private CardDavBackend $cardDavBackend; - private CalDavBackend $calDavBackend; - - public function __construct(ITimeFactory $timeFactory, CalDavBackend $calDavBackend, CardDavBackend $cardDavBackend, IConfig $config, LoggerInterface $logger) { + public function __construct( + ITimeFactory $timeFactory, + private CalDavBackend $calDavBackend, + private CardDavBackend $cardDavBackend, + private IConfig $config, + private LoggerInterface $logger, + ) { parent::__construct($timeFactory); - $this->calDavBackend = $calDavBackend; - $this->cardDavBackend = $cardDavBackend; - $this->config = $config; - $this->logger = $logger; $this->setInterval(60 * 60 * 24); // One day $this->setTimeSensitivity(self::TIME_INSENSITIVE); } public function run($argument) { - $limit = max(1, (int) $this->config->getAppValue(Application::APP_ID, 'totalNumberOfSyncTokensToKeep', '10000')); - $retention = max(7, (int) $this->config->getAppValue(Application::APP_ID, 'syncTokensRetentionDays', '60')) * 24 * 3600; + $limit = max(1, (int)$this->config->getAppValue(Application::APP_ID, 'totalNumberOfSyncTokensToKeep', '10000')); + $retention = max(7, (int)$this->config->getAppValue(Application::APP_ID, 'syncTokensRetentionDays', '60')) * 24 * 3600; $prunedCalendarSyncTokens = $this->calDavBackend->pruneOutdatedSyncTokens($limit, $retention); $prunedAddressBookSyncTokens = $this->cardDavBackend->pruneOutdatedSyncTokens($limit, $retention); diff --git a/apps/dav/lib/BackgroundJob/RefreshWebcalJob.php b/apps/dav/lib/BackgroundJob/RefreshWebcalJob.php index 982d6040fd7..e96735ca50b 100644 --- a/apps/dav/lib/BackgroundJob/RefreshWebcalJob.php +++ b/apps/dav/lib/BackgroundJob/RefreshWebcalJob.php @@ -41,8 +41,8 @@ class RefreshWebcalJob extends Job { $this->fixSubscriptionRowTyping($subscription); - // if no refresh rate was configured, just refresh once a week - $defaultRefreshRate = $this->config->getAppValue('dav', 'calendarSubscriptionRefreshRate', 'P1W'); + // if no refresh rate was configured, just refresh once a day + $defaultRefreshRate = $this->config->getAppValue('dav', 'calendarSubscriptionRefreshRate', 'P1D'); $refreshRate = $subscription[RefreshWebcalService::REFRESH_RATE] ?? $defaultRefreshRate; $subscriptionId = $subscription['id']; @@ -104,7 +104,7 @@ class RefreshWebcalJob extends Job { foreach ($forceInt as $column) { if (isset($row[$column])) { - $row[$column] = (int) $row[$column]; + $row[$column] = (int)$row[$column]; } } } diff --git a/apps/dav/lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php b/apps/dav/lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php index 61fe4cd8483..7ec5b7fba79 100644 --- a/apps/dav/lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php +++ b/apps/dav/lib/BackgroundJob/RegisterRegenerateBirthdayCalendars.php @@ -16,12 +16,6 @@ use OCP\IUserManager; class RegisterRegenerateBirthdayCalendars extends QueuedJob { - /** @var IUserManager */ - private $userManager; - - /** @var IJobList */ - private $jobList; - /** * RegisterRegenerateBirthdayCalendars constructor. * @@ -29,19 +23,19 @@ class RegisterRegenerateBirthdayCalendars extends QueuedJob { * @param IUserManager $userManager * @param IJobList $jobList */ - public function __construct(ITimeFactory $time, - IUserManager $userManager, - IJobList $jobList) { + public function __construct( + ITimeFactory $time, + private IUserManager $userManager, + private IJobList $jobList, + ) { parent::__construct($time); - $this->userManager = $userManager; - $this->jobList = $jobList; } /** * @inheritDoc */ public function run($argument) { - $this->userManager->callForSeenUsers(function (IUser $user) { + $this->userManager->callForSeenUsers(function (IUser $user): void { $this->jobList->add(GenerateBirthdayCalendarBackgroundJob::class, [ 'userId' => $user->getUID(), 'purgeBeforeGenerating' => true diff --git a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php index 3ce90c72019..b7688ea32d8 100644 --- a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php +++ b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php @@ -9,427 +9,26 @@ declare(strict_types=1); namespace OCA\DAV\BackgroundJob; -use OCA\DAV\CalDAV\CalDavBackend; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; -use OCP\Calendar\BackendTemporarilyUnavailableException; -use OCP\Calendar\IMetadataProvider; -use OCP\Calendar\Resource\IBackend as IResourceBackend; use OCP\Calendar\Resource\IManager as IResourceManager; -use OCP\Calendar\Resource\IResource; use OCP\Calendar\Room\IManager as IRoomManager; -use OCP\Calendar\Room\IRoom; -use OCP\IDBConnection; class UpdateCalendarResourcesRoomsBackgroundJob extends TimedJob { - - /** @var IResourceManager */ - private $resourceManager; - - /** @var IRoomManager */ - private $roomManager; - - /** @var IDBConnection */ - private $dbConnection; - - /** @var CalDavBackend */ - private $calDavBackend; - - public function __construct(ITimeFactory $time, - IResourceManager $resourceManager, - IRoomManager $roomManager, - IDBConnection $dbConnection, - CalDavBackend $calDavBackend) { + public function __construct( + ITimeFactory $time, + private IResourceManager $resourceManager, + private IRoomManager $roomManager, + ) { parent::__construct($time); - $this->resourceManager = $resourceManager; - $this->roomManager = $roomManager; - $this->dbConnection = $dbConnection; - $this->calDavBackend = $calDavBackend; // Run once an hour $this->setInterval(60 * 60); $this->setTimeSensitivity(self::TIME_SENSITIVE); } - /** - * @param $argument - */ public function run($argument): void { - $this->runForBackend( - $this->resourceManager, - 'calendar_resources', - 'calendar_resources_md', - 'resource_id', - 'principals/calendar-resources' - ); - $this->runForBackend( - $this->roomManager, - 'calendar_rooms', - 'calendar_rooms_md', - 'room_id', - 'principals/calendar-rooms' - ); - } - - /** - * Run background-job for one specific backendManager - * either ResourceManager or RoomManager - * - * @param IResourceManager|IRoomManager $backendManager - * @param string $dbTable - * @param string $dbTableMetadata - * @param string $foreignKey - * @param string $principalPrefix - */ - private function runForBackend($backendManager, - string $dbTable, - string $dbTableMetadata, - string $foreignKey, - string $principalPrefix): void { - $backends = $backendManager->getBackends(); - - foreach ($backends as $backend) { - $backendId = $backend->getBackendIdentifier(); - - try { - if ($backend instanceof IResourceBackend) { - $list = $backend->listAllResources(); - } else { - $list = $backend->listAllRooms(); - } - } catch (BackendTemporarilyUnavailableException $ex) { - continue; - } - - $cachedList = $this->getAllCachedByBackend($dbTable, $backendId); - $newIds = array_diff($list, $cachedList); - $deletedIds = array_diff($cachedList, $list); - $editedIds = array_intersect($list, $cachedList); - - foreach ($newIds as $newId) { - try { - if ($backend instanceof IResourceBackend) { - $resource = $backend->getResource($newId); - } else { - $resource = $backend->getRoom($newId); - } - - $metadata = []; - if ($resource instanceof IMetadataProvider) { - $metadata = $this->getAllMetadataOfBackend($resource); - } - } catch (BackendTemporarilyUnavailableException $ex) { - continue; - } - - $id = $this->addToCache($dbTable, $backendId, $resource); - $this->addMetadataToCache($dbTableMetadata, $foreignKey, $id, $metadata); - // we don't create the calendar here, it is created lazily - // when an event is actually scheduled with this resource / room - } - - foreach ($deletedIds as $deletedId) { - $id = $this->getIdForBackendAndResource($dbTable, $backendId, $deletedId); - $this->deleteFromCache($dbTable, $id); - $this->deleteMetadataFromCache($dbTableMetadata, $foreignKey, $id); - - $principalName = implode('-', [$backendId, $deletedId]); - $this->deleteCalendarDataForResource($principalPrefix, $principalName); - } - - foreach ($editedIds as $editedId) { - $id = $this->getIdForBackendAndResource($dbTable, $backendId, $editedId); - - try { - if ($backend instanceof IResourceBackend) { - $resource = $backend->getResource($editedId); - } else { - $resource = $backend->getRoom($editedId); - } - - $metadata = []; - if ($resource instanceof IMetadataProvider) { - $metadata = $this->getAllMetadataOfBackend($resource); - } - } catch (BackendTemporarilyUnavailableException $ex) { - continue; - } - - $this->updateCache($dbTable, $id, $resource); - - if ($resource instanceof IMetadataProvider) { - $cachedMetadata = $this->getAllMetadataOfCache($dbTableMetadata, $foreignKey, $id); - $this->updateMetadataCache($dbTableMetadata, $foreignKey, $id, $metadata, $cachedMetadata); - } - } - } - } - - /** - * add entry to cache that exists remotely but not yet in cache - * - * @param string $table - * @param string $backendId - * @param IResource|IRoom $remote - * - * @return int Insert id - */ - private function addToCache(string $table, - string $backendId, - $remote): int { - $query = $this->dbConnection->getQueryBuilder(); - $query->insert($table) - ->values([ - 'backend_id' => $query->createNamedParameter($backendId), - 'resource_id' => $query->createNamedParameter($remote->getId()), - 'email' => $query->createNamedParameter($remote->getEMail()), - 'displayname' => $query->createNamedParameter($remote->getDisplayName()), - 'group_restrictions' => $query->createNamedParameter( - $this->serializeGroupRestrictions( - $remote->getGroupRestrictions() - )) - ]) - ->executeStatement(); - return $query->getLastInsertId(); - } - - /** - * @param string $table - * @param string $foreignKey - * @param int $foreignId - * @param array $metadata - */ - private function addMetadataToCache(string $table, - string $foreignKey, - int $foreignId, - array $metadata): void { - foreach ($metadata as $key => $value) { - $query = $this->dbConnection->getQueryBuilder(); - $query->insert($table) - ->values([ - $foreignKey => $query->createNamedParameter($foreignId), - 'key' => $query->createNamedParameter($key), - 'value' => $query->createNamedParameter($value), - ]) - ->executeStatement(); - } - } - - /** - * delete entry from cache that does not exist anymore remotely - * - * @param string $table - * @param int $id - */ - private function deleteFromCache(string $table, - int $id): void { - $query = $this->dbConnection->getQueryBuilder(); - $query->delete($table) - ->where($query->expr()->eq('id', $query->createNamedParameter($id))) - ->executeStatement(); - } - - /** - * @param string $table - * @param string $foreignKey - * @param int $id - */ - private function deleteMetadataFromCache(string $table, - string $foreignKey, - int $id): void { - $query = $this->dbConnection->getQueryBuilder(); - $query->delete($table) - ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id))) - ->executeStatement(); - } - - /** - * update an existing entry in cache - * - * @param string $table - * @param int $id - * @param IResource|IRoom $remote - */ - private function updateCache(string $table, - int $id, - $remote): void { - $query = $this->dbConnection->getQueryBuilder(); - $query->update($table) - ->set('email', $query->createNamedParameter($remote->getEMail())) - ->set('displayname', $query->createNamedParameter($remote->getDisplayName())) - ->set('group_restrictions', $query->createNamedParameter( - $this->serializeGroupRestrictions( - $remote->getGroupRestrictions() - ))) - ->where($query->expr()->eq('id', $query->createNamedParameter($id))) - ->executeStatement(); - } - - /** - * @param string $dbTable - * @param string $foreignKey - * @param int $id - * @param array $metadata - * @param array $cachedMetadata - */ - private function updateMetadataCache(string $dbTable, - string $foreignKey, - int $id, - array $metadata, - array $cachedMetadata): void { - $newMetadata = array_diff_key($metadata, $cachedMetadata); - $deletedMetadata = array_diff_key($cachedMetadata, $metadata); - - foreach ($newMetadata as $key => $value) { - $query = $this->dbConnection->getQueryBuilder(); - $query->insert($dbTable) - ->values([ - $foreignKey => $query->createNamedParameter($id), - 'key' => $query->createNamedParameter($key), - 'value' => $query->createNamedParameter($value), - ]) - ->executeStatement(); - } - - foreach ($deletedMetadata as $key => $value) { - $query = $this->dbConnection->getQueryBuilder(); - $query->delete($dbTable) - ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id))) - ->andWhere($query->expr()->eq('key', $query->createNamedParameter($key))) - ->executeStatement(); - } - - $existingKeys = array_keys(array_intersect_key($metadata, $cachedMetadata)); - foreach ($existingKeys as $existingKey) { - if ($metadata[$existingKey] !== $cachedMetadata[$existingKey]) { - $query = $this->dbConnection->getQueryBuilder(); - $query->update($dbTable) - ->set('value', $query->createNamedParameter($metadata[$existingKey])) - ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id))) - ->andWhere($query->expr()->eq('key', $query->createNamedParameter($existingKey))) - ->executeStatement(); - } - } - } - - /** - * serialize array of group restrictions to store them in database - * - * @param array $groups - * - * @return string - */ - private function serializeGroupRestrictions(array $groups): string { - return \json_encode($groups, JSON_THROW_ON_ERROR); - } - - /** - * Gets all metadata of a backend - * - * @param IResource|IRoom $resource - * - * @return array - */ - private function getAllMetadataOfBackend($resource): array { - if (!($resource instanceof IMetadataProvider)) { - return []; - } - - $keys = $resource->getAllAvailableMetadataKeys(); - $metadata = []; - foreach ($keys as $key) { - $metadata[$key] = $resource->getMetadataForKey($key); - } - - return $metadata; - } - - /** - * @param string $table - * @param string $foreignKey - * @param int $id - * - * @return array - */ - private function getAllMetadataOfCache(string $table, - string $foreignKey, - int $id): array { - $query = $this->dbConnection->getQueryBuilder(); - $query->select(['key', 'value']) - ->from($table) - ->where($query->expr()->eq($foreignKey, $query->createNamedParameter($id))); - $result = $query->executeQuery(); - $rows = $result->fetchAll(); - $result->closeCursor(); - - $metadata = []; - foreach ($rows as $row) { - $metadata[$row['key']] = $row['value']; - } - - return $metadata; - } - - /** - * Gets all cached rooms / resources by backend - * - * @param $tableName - * @param $backendId - * - * @return array - */ - private function getAllCachedByBackend(string $tableName, - string $backendId): array { - $query = $this->dbConnection->getQueryBuilder(); - $query->select('resource_id') - ->from($tableName) - ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId))); - $result = $query->executeQuery(); - $rows = $result->fetchAll(); - $result->closeCursor(); - - return array_map(function ($row): string { - return $row['resource_id']; - }, $rows); - } - - /** - * @param $principalPrefix - * @param $principalUri - */ - private function deleteCalendarDataForResource(string $principalPrefix, - string $principalUri): void { - $calendar = $this->calDavBackend->getCalendarByUri( - implode('/', [$principalPrefix, $principalUri]), - CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI); - - if ($calendar !== null) { - $this->calDavBackend->deleteCalendar( - $calendar['id'], - true // Because this wasn't deleted by a user - ); - } - } - - /** - * @param $table - * @param $backendId - * @param $resourceId - * - * @return int - */ - private function getIdForBackendAndResource(string $table, - string $backendId, - string $resourceId): int { - $query = $this->dbConnection->getQueryBuilder(); - $query->select('id') - ->from($table) - ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId))) - ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId))); - $result = $query->executeQuery(); - - $id = (int) $result->fetchOne(); - $result->closeCursor(); - return $id; + $this->resourceManager->update(); + $this->roomManager->update(); } } diff --git a/apps/dav/lib/BackgroundJob/UploadCleanup.php b/apps/dav/lib/BackgroundJob/UploadCleanup.php index 59a28626ecd..230cde61578 100644 --- a/apps/dav/lib/BackgroundJob/UploadCleanup.php +++ b/apps/dav/lib/BackgroundJob/UploadCleanup.php @@ -10,7 +10,6 @@ namespace OCA\DAV\BackgroundJob; use OC\User\NoUserException; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\BackgroundJob\IJob; use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\TimedJob; use OCP\Files\File; @@ -20,19 +19,17 @@ use OCP\Files\NotFoundException; use Psr\Log\LoggerInterface; class UploadCleanup extends TimedJob { - private IRootFolder $rootFolder; - private IJobList $jobList; - private LoggerInterface $logger; - - public function __construct(ITimeFactory $time, IRootFolder $rootFolder, IJobList $jobList, LoggerInterface $logger) { + public function __construct( + ITimeFactory $time, + private IRootFolder $rootFolder, + private IJobList $jobList, + private LoggerInterface $logger, + ) { parent::__construct($time); - $this->rootFolder = $rootFolder; - $this->jobList = $jobList; - $this->logger = $logger; // Run once a day $this->setInterval(60 * 60 * 24); - $this->setTimeSensitivity(IJob::TIME_INSENSITIVE); + $this->setTimeSensitivity(self::TIME_INSENSITIVE); } protected function run($argument) { @@ -45,7 +42,7 @@ class UploadCleanup extends TimedJob { /** @var Folder $uploads */ $uploads = $userRoot->get('uploads'); $uploadFolder = $uploads->get($folder); - } catch (NotFoundException | NoUserException $e) { + } catch (NotFoundException|NoUserException $e) { $this->jobList->remove(self::class, $argument); return; } @@ -54,7 +51,7 @@ class UploadCleanup extends TimedJob { $time = $this->time->getTime() - 60 * 60 * 24; if (!($uploadFolder instanceof Folder)) { - $this->logger->error("Found a file inside the uploads folder. Uid: " . $uid . ' folder: ' . $folder); + $this->logger->error('Found a file inside the uploads folder. Uid: ' . $uid . ' folder: ' . $folder); if ($uploadFolder->getMTime() < $time) { $uploadFolder->delete(); } diff --git a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php index e17fa604ab9..027b3349802 100644 --- a/apps/dav/lib/BackgroundJob/UserStatusAutomation.php +++ b/apps/dav/lib/BackgroundJob/UserStatusAutomation.php @@ -28,18 +28,21 @@ use Sabre\VObject\Reader; use Sabre\VObject\Recur\RRuleIterator; class UserStatusAutomation extends TimedJob { - public function __construct(private ITimeFactory $timeFactory, + public function __construct( + private ITimeFactory $timeFactory, private IDBConnection $connection, private IJobList $jobList, private LoggerInterface $logger, private IManager $manager, private IConfig $config, private IAvailabilityCoordinator $coordinator, - private IUserManager $userManager) { + private IUserManager $userManager, + ) { parent::__construct($timeFactory); - // Interval 0 might look weird, but the last_checked is always moved - // to the next time we need this and then it's 0 seconds ago. + // interval = 0 might look odd, but it's intentional. last_run is set to + // the user's next available time, so the job runs immediately when + // that time comes. $this->setInterval(0); } @@ -55,14 +58,14 @@ class UserStatusAutomation extends TimedJob { $userId = $argument['userId']; $user = $this->userManager->get($userId); - if($user === null) { + if ($user === null) { return; } $ooo = $this->coordinator->getCurrentOutOfOfficeData($user); $continue = $this->processOutOfOfficeData($user, $ooo); - if($continue === false) { + if ($continue === false) { return; } @@ -196,20 +199,18 @@ class UserStatusAutomation extends TimedJob { return; } - if(!$hasDndForOfficeHours) { + if (!$hasDndForOfficeHours) { // Office hours are not set to DND, so there is nothing to do. return; } - $this->logger->debug('User is currently NOT available, reverting call status if applicable and then setting DND'); - // The DND status automation is more important than the "Away - In call" so we also restore that one if it exists. - $this->manager->revertUserStatus($userId, IUserStatus::MESSAGE_CALL, IUserStatus::AWAY); + $this->logger->debug('User is currently NOT available, reverting call and meeting status if applicable and then setting DND'); $this->manager->setUserStatus($userId, IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::DND, true); $this->logger->debug('User status automation ran'); } private function processOutOfOfficeData(IUser $user, ?IOutOfOfficeData $ooo): bool { - if(empty($ooo)) { + if (empty($ooo)) { // Reset the user status if the absence doesn't exist $this->logger->debug('User has no OOO period in effect, reverting DND status if applicable'); $this->manager->revertUserStatus($user->getUID(), IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::DND); @@ -217,12 +218,12 @@ class UserStatusAutomation extends TimedJob { return true; } - if(!$this->coordinator->isInEffect($ooo)) { + if (!$this->coordinator->isInEffect($ooo)) { // Reset the user status if the absence is (no longer) in effect $this->logger->debug('User has no OOO period in effect, reverting DND status if applicable'); $this->manager->revertUserStatus($user->getUID(), IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::DND); - if($ooo->getStartDate() > $this->time->getTime()) { + if ($ooo->getStartDate() > $this->time->getTime()) { // Set the next run to take place at the start of the ooo period if it is in the future // This might be overwritten if there is an availability setting, but we can't determine // if this is the case here @@ -232,10 +233,8 @@ class UserStatusAutomation extends TimedJob { } $this->logger->debug('User is currently in an OOO period, reverting other automated status and setting OOO DND status'); - // Revert both a possible 'CALL - away' and 'office hours - DND' status - $this->manager->revertUserStatus($user->getUID(), IUserStatus::MESSAGE_CALL, IUserStatus::DND); - $this->manager->revertUserStatus($user->getUID(), IUserStatus::MESSAGE_AVAILABILITY, IUserStatus::DND); $this->manager->setUserStatus($user->getUID(), IUserStatus::MESSAGE_OUT_OF_OFFICE, IUserStatus::DND, true, $ooo->getShortMessage()); + // Run at the end of an ooo period to return to availability / regular user status // If it's overwritten by a custom status in the meantime, there's nothing we can do about it $this->setLastRunToNextToggleTime($user->getUID(), $ooo->getEndDate()); |