aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorskjnldsv <skjnldsv@protonmail.com>2024-10-22 15:56:03 +0200
committerskjnldsv <skjnldsv@protonmail.com>2024-10-29 09:08:31 +0100
commit14e2a8d3f982656e2a7c23c006fd59fdeebc80bd (patch)
tree216f9b391e4815daed88dbbf475252ad89fc42ae /lib
parentf24b93e5067e54244d14eb08ad8ed8330a03724b (diff)
downloadnextcloud-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.php2
-rw-r--r--lib/private/SystemTag/SystemTag.php8
-rw-r--r--lib/private/SystemTag/SystemTagManager.php3
-rw-r--r--lib/private/SystemTag/SystemTagObjectMapper.php56
-rw-r--r--lib/public/SystemTag/ISystemTag.php9
-rw-r--r--lib/public/SystemTag/ISystemTagObjectMapper.php13
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;
}