diff --git a/apps/dav/lib/Connector/Sabre/TagsPlugin.php b/apps/dav/lib/Connector/Sabre/TagsPlugin.php index 7baf1742d61bb..c9e287cb5812b 100644 --- a/apps/dav/lib/Connector/Sabre/TagsPlugin.php +++ b/apps/dav/lib/Connector/Sabre/TagsPlugin.php @@ -41,7 +41,7 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin { public const NS_OWNCLOUD = 'http://owncloud.org/ns'; public const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags'; public const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite'; - public const TAG_FAVORITE = '_$!!$_'; + public const TAG_FAVORITE = ITags::TAG_FAVORITE; /** * Reference to main server object diff --git a/apps/files/lib/Service/TagService.php b/apps/files/lib/Service/TagService.php index 95176ce95fae0..eef886a97061e 100644 --- a/apps/files/lib/Service/TagService.php +++ b/apps/files/lib/Service/TagService.php @@ -44,6 +44,9 @@ public function updateFileTags($path, $tags) { throw new \RuntimeException('No homeFolder set'); } + // Only handle the favorite tag + $tags = array_filter($tags, static fn (string $tag): bool => $tag === ITags::TAG_FAVORITE); + $fileId = $this->homeFolder->get($path)->getId(); $currentTags = $this->tagger->getTagsForObjects([$fileId]); diff --git a/apps/files/tests/Service/TagServiceTest.php b/apps/files/tests/Service/TagServiceTest.php index 1b3e0898b334a..8e1196b91e884 100644 --- a/apps/files/tests/Service/TagServiceTest.php +++ b/apps/files/tests/Service/TagServiceTest.php @@ -79,8 +79,7 @@ protected function tearDown(): void { } public function testUpdateFileTags(): void { - $tag1 = 'tag1'; - $tag2 = 'tag2'; + $tag1 = ITags::TAG_FAVORITE; $subdir = $this->root->newFolder('subdir'); $testFile = $subdir->newFile('test.txt'); @@ -89,20 +88,13 @@ public function testUpdateFileTags(): void { $fileId = $testFile->getId(); // set tags - $this->tagService->updateFileTags('subdir/test.txt', [$tag1, $tag2]); + $this->tagService->updateFileTags('subdir/test.txt', [$tag1]); $this->assertEquals([$fileId], $this->tagger->getIdsForTag($tag1)); - $this->assertEquals([$fileId], $this->tagger->getIdsForTag($tag2)); - - // remove tag - $this->tagService->updateFileTags('subdir/test.txt', [$tag2]); - $this->assertEquals([], $this->tagger->getIdsForTag($tag1)); - $this->assertEquals([$fileId], $this->tagger->getIdsForTag($tag2)); // clear tags $this->tagService->updateFileTags('subdir/test.txt', []); $this->assertEquals([], $this->tagger->getIdsForTag($tag1)); - $this->assertEquals([], $this->tagger->getIdsForTag($tag2)); // non-existing file $caught = false; diff --git a/lib/private/Tags.php b/lib/private/Tags.php index fcca3d96b7ac1..301f7d8c5a4f8 100644 --- a/lib/private/Tags.php +++ b/lib/private/Tags.php @@ -199,17 +199,12 @@ public function getTagsForObjects(array $objIds) { * @throws \Exception */ public function getIdsForTag($tag) { - $tagId = false; - if (is_numeric($tag)) { - $tagId = $tag; - } elseif (is_string($tag)) { - $tag = trim($tag); - if ($tag === '') { - $this->logger->debug(__METHOD__ . ' Cannot use empty tag names', ['app' => 'core']); - return false; - } - $tagId = $this->getTagId($tag); + $tag = trim((string)$tag); + if ($tag === '') { + $this->logger->debug(__METHOD__ . ' Cannot use empty tag names', ['app' => 'core']); + return false; } + $tagId = $this->getTagIdByIdOrName($tag); if ($tagId === false) { $l10n = \OCP\Util::getL10N('core'); @@ -499,18 +494,15 @@ public function removeFromFavorites($objid) { * Creates a tag/object relation. */ public function tagAs($objid, $tag, ?string $path = null) { - if (is_string($tag) && !is_numeric($tag)) { - $tag = trim($tag); - if ($tag === '') { - $this->logger->debug(__METHOD__ . ', Cannot add an empty tag'); - return false; - } - if (!$this->hasTag($tag)) { - $this->add($tag); - } + $tag = trim((string)$tag); + if ($tag === '') { + $this->logger->debug(__METHOD__ . ', Cannot add an empty tag'); + return false; + } + $tagId = $this->getTagIdByIdOrName($tag); + if ($tagId === false) { + $this->add($tag); $tagId = $this->getTagId($tag); - } else { - $tagId = $tag; } $qb = $this->db->getQueryBuilder(); $qb->insert(self::RELATION_TABLE) @@ -547,16 +539,12 @@ public function tagAs($objid, $tag, ?string $path = null) { * Delete single tag/object relation from the db */ public function unTag($objid, $tag, ?string $path = null) { - if (is_string($tag) && !is_numeric($tag)) { - $tag = trim($tag); - if ($tag === '') { - $this->logger->debug(__METHOD__ . ', Tag name is empty'); - return false; - } - $tagId = $this->getTagId($tag); - } else { - $tagId = $tag; + $tag = trim((string)$tag); + if ($tag === '') { + $this->logger->debug(__METHOD__ . ', Tag name is empty'); + return false; } + $tagId = $this->getTagIdByIdOrName($tag); try { $qb = $this->db->getQueryBuilder(); @@ -664,6 +652,24 @@ private function getTagId($name) { return false; } + /** + * Get a tag's ID from either its ID or its name. + * + * A numeric value is only accepted as ID if it is the ID of one of the loaded tags. + * + * @param string $tag The tag ID or name to look for. + * @return string|bool The tag's id or false if no matching tag is found. + */ + private function getTagIdByIdOrName(string $tag) { + if (is_numeric($tag)) { + $key = $this->getTagById($tag); + if ($key !== false) { + return $this->tags[$key]->id ?? false; + } + } + return $this->getTagId($tag); + } + /** * Get a tag by its name. * diff --git a/tests/lib/TagsTest.php b/tests/lib/TagsTest.php index 6dc43300dfcff..be11042054af6 100644 --- a/tests/lib/TagsTest.php +++ b/tests/lib/TagsTest.php @@ -304,6 +304,38 @@ public function testUnTag(): void { $this->assertEquals(0, count($tagger->getIdsForTag('Family'))); } + public function testTagById(): void { + $tagger = $this->tagMgr->load($this->objectType); + $tagId = $tagger->add('Family'); + + $this->assertTrue($tagger->tagAs(1, (string)$tagId)); + $this->assertEquals([1], $tagger->getIdsForTag('Family')); + $this->assertEquals([1], $tagger->getIdsForTag($tagId)); + $this->assertTrue($tagger->unTag(1, (string)$tagId)); + $this->assertEquals([], $tagger->getIdsForTag('Family')); + $this->assertEquals(1, count($tagger->getTags())); + } + + public function testTagByNumericValue(): void { + $otherTagger = $this->tagMgr->load($this->objectType, [], false, self::getUniqueID('user_')); + $otherTagId = $otherTagger->add('Family'); + $this->assertTrue($otherTagger->tagAs(1, 'Family')); + + $tagger = $this->tagMgr->load($this->objectType); + + // Treated as the name of an own tag + $this->assertTrue($tagger->tagAs(2, (string)$otherTagId)); + $this->assertTrue($tagger->hasTag((string)$otherTagId)); + $this->assertEquals([2], $tagger->getIdsForTag((string)$otherTagId)); + $this->assertEquals([1], $otherTagger->getIdsForTag('Family')); + + $tagger->unTag(1, (string)$otherTagId); + $this->assertEquals([1], $otherTagger->getIdsForTag('Family')); + + $tagger->unTag(2, (string)$otherTagId); + $this->assertEquals([], $tagger->getIdsForTag((string)$otherTagId)); + } + public function testFavorite(): void { $tagger = $this->tagMgr->load($this->objectType); $this->assertTrue($tagger->addToFavorites(1));