diff options
author | skjnldsv <skjnldsv@protonmail.com> | 2024-10-22 15:56:03 +0200 |
---|---|---|
committer | skjnldsv <skjnldsv@protonmail.com> | 2024-10-29 09:08:31 +0100 |
commit | 14e2a8d3f982656e2a7c23c006fd59fdeebc80bd (patch) | |
tree | 216f9b391e4815daed88dbbf475252ad89fc42ae /lib | |
parent | f24b93e5067e54244d14eb08ad8ed8330a03724b (diff) | |
download | nextcloud-server-14e2a8d3f982656e2a7c23c006fd59fdeebc80bd.tar.gz nextcloud-server-14e2a8d3f982656e2a7c23c006fd59fdeebc80bd.zip |
feat(systemtags): add etag support and handle proppatch
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Files/Cache/CacheQueryBuilder.php | 2 | ||||
-rw-r--r-- | lib/private/SystemTag/SystemTag.php | 8 | ||||
-rw-r--r-- | lib/private/SystemTag/SystemTagManager.php | 3 | ||||
-rw-r--r-- | lib/private/SystemTag/SystemTagObjectMapper.php | 56 | ||||
-rw-r--r-- | lib/public/SystemTag/ISystemTag.php | 9 | ||||
-rw-r--r-- | lib/public/SystemTag/ISystemTagObjectMapper.php | 13 |
6 files changed, 89 insertions, 2 deletions
diff --git a/lib/private/Files/Cache/CacheQueryBuilder.php b/lib/private/Files/Cache/CacheQueryBuilder.php index 76eb2bfa5ca..2853ca033ad 100644 --- a/lib/private/Files/Cache/CacheQueryBuilder.php +++ b/lib/private/Files/Cache/CacheQueryBuilder.php @@ -28,7 +28,7 @@ class CacheQueryBuilder extends ExtendedQueryBuilder { public function selectTagUsage(): self { $this - ->select('systemtag.name', 'systemtag.id', 'systemtag.visibility', 'systemtag.editable') + ->select('systemtag.name', 'systemtag.id', 'systemtag.visibility', 'systemtag.editable', 'systemtag.etag') ->selectAlias($this->createFunction('COUNT(filecache.fileid)'), 'number_files') ->selectAlias($this->createFunction('MAX(filecache.fileid)'), 'ref_file_id') ->from('filecache', 'filecache') diff --git a/lib/private/SystemTag/SystemTag.php b/lib/private/SystemTag/SystemTag.php index 83fb6bc7f93..be97bed27dd 100644 --- a/lib/private/SystemTag/SystemTag.php +++ b/lib/private/SystemTag/SystemTag.php @@ -16,6 +16,7 @@ class SystemTag implements ISystemTag { private string $name, private bool $userVisible, private bool $userAssignable, + private ?string $etag = null, ) { } @@ -61,4 +62,11 @@ class SystemTag implements ISystemTag { return self::ACCESS_LEVEL_PUBLIC; } + + /** + * {@inheritdoc} + */ + public function getEtag(): ?string { + return $this->etag; + } } diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index cbba9968656..70bb8e6e70b 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -165,6 +165,7 @@ class SystemTagManager implements ISystemTagManager { 'name' => $query->createNamedParameter($truncatedTagName), 'visibility' => $query->createNamedParameter($userVisible ? 1 : 0), 'editable' => $query->createNamedParameter($userAssignable ? 1 : 0), + 'etag' => $query->createNamedParameter(md5((string)time())), ]); try { @@ -360,7 +361,7 @@ class SystemTagManager implements ISystemTagManager { } private function createSystemTagFromRow($row): SystemTag { - return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']); + return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable'], $row['etag']); } /** diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php index 0bfc03a1227..ddb04fa968d 100644 --- a/lib/private/SystemTag/SystemTagObjectMapper.php +++ b/lib/private/SystemTag/SystemTagObjectMapper.php @@ -156,6 +156,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { } } + $this->updateEtagForTags($tagIds); + $this->connection->commit(); if (empty($tagsAssigned)) { return; @@ -189,6 +191,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { ->setParameter('tagids', $tagIds, IQueryBuilder::PARAM_INT_ARRAY) ->executeStatement(); + $this->updateEtagForTags($tagIds); + $this->dispatcher->dispatch(MapperEvent::EVENT_UNASSIGN, new MapperEvent( MapperEvent::EVENT_UNASSIGN, $objectType, @@ -198,6 +202,21 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { } /** + * Update the etag for the given tags. + * + * @param int[] $tagIds + */ + private function updateEtagForTags(array $tagIds): void { + // Update etag after assigning tags + $md5 = md5(json_encode(time())); + $query = $this->connection->getQueryBuilder(); + $query->update('systemtag') + ->set('etag', $query->createNamedParameter($md5)) + ->where($query->expr()->in('id', $query->createNamedParameter($tagIds, IQueryBuilder::PARAM_INT_ARRAY))); + $query->execute(); + } + + /** * {@inheritdoc} */ public function haveTag($objIds, string $objectType, string $tagId, bool $all = true): bool { @@ -261,6 +280,43 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { } } + /** + * {@inheritdoc} + */ + public function setObjectIdsForTag(string $tagId, string $objectType, array $objectIds): void { + $this->connection->beginTransaction(); + $query = $this->connection->getQueryBuilder(); + $query->delete(self::RELATION_TABLE) + ->where($query->expr()->eq('systemtagid', $query->createNamedParameter($tagId, IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->eq('objecttype', $query->createNamedParameter($objectType))) + ->executeStatement(); + $this->connection->commit(); + + if (empty($objectIds)) { + return; + } + + $this->connection->beginTransaction(); + $query = $this->connection->getQueryBuilder(); + $query->insert(self::RELATION_TABLE) + ->values([ + 'systemtagid' => $query->createNamedParameter($tagId, IQueryBuilder::PARAM_INT), + 'objecttype' => $query->createNamedParameter($objectType), + 'objectid' => $query->createParameter('objectid'), + ]); + + foreach (array_unique($objectIds) as $objectId) { + $query->setParameter('objectid', (string)$objectId); + $query->executeStatement(); + } + + $this->updateEtagForTags([$tagId]); + $this->connection->commit(); + } + + /** + * {@inheritdoc} + */ public function getAvailableObjectTypes(): array { $query = $this->connection->getQueryBuilder(); $query->selectDistinct('objecttype') diff --git a/lib/public/SystemTag/ISystemTag.php b/lib/public/SystemTag/ISystemTag.php index 8a01779f783..77575494d16 100644 --- a/lib/public/SystemTag/ISystemTag.php +++ b/lib/public/SystemTag/ISystemTag.php @@ -80,4 +80,13 @@ interface ISystemTag { * @since 22.0.0 */ public function getAccessLevel(): int; + + /** + * Returns the ETag of the tag + * The ETag is a unique identifier for the tag and should change whenever the tag changes + * or whenever elements gets added or removed from the tag. + * + * @since 31.0.0 + */ + public function getEtag(): ?string; } diff --git a/lib/public/SystemTag/ISystemTagObjectMapper.php b/lib/public/SystemTag/ISystemTagObjectMapper.php index cd4c3495171..96e8c1e848a 100644 --- a/lib/public/SystemTag/ISystemTagObjectMapper.php +++ b/lib/public/SystemTag/ISystemTagObjectMapper.php @@ -121,4 +121,17 @@ interface ISystemTagObjectMapper { * @since 31.0.0 */ public function getAvailableObjectTypes(): array; + + /** + * Set the list of object ids for the given tag. + * This will replace the current list of object ids. + * + * @param string $tagId tag id + * @param string $objectType object type + * @param string[] $objectIds list of object ids + * + * @throws TagNotFoundException if the tag does not exist + * @since 31.0.0 + */ + public function setObjectIdsForTag(string $tagId, string $objectType, array $objectIds): void; } |