aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav/lib/BackgroundJob
diff options
context:
space:
mode:
authorRichard Steinmetz <richard@steinmetz.cloud>2024-05-16 21:27:07 +0200
committerRichard Steinmetz <richard@steinmetz.cloud>2024-05-27 18:45:52 +0200
commit69e0158030e49b3d16276b8488d5dd1c6ffa023b (patch)
treeb72b308b61e4c56ba8610aad3b9c663e986acfb8 /apps/dav/lib/BackgroundJob
parentbb1cb1c2315627964afe26316c661b9c591f26b1 (diff)
downloadnextcloud-server-69e0158030e49b3d16276b8488d5dd1c6ffa023b.tar.gz
nextcloud-server-69e0158030e49b3d16276b8488d5dd1c6ffa023b.zip
feat: implement public OCP api to update resources and rooms
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
Diffstat (limited to 'apps/dav/lib/BackgroundJob')
-rw-r--r--apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php415
1 files changed, 7 insertions, 408 deletions
diff --git a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php
index b4571e2509d..670abd2662a 100644
--- a/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php
+++ b/apps/dav/lib/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJob.php
@@ -28,427 +28,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();
}
}