aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2023-04-28 13:37:16 +0200
committerGitHub <noreply@github.com>2023-04-28 13:37:16 +0200
commit74f31bac8c0473f3dc92fcb54967f4cf977c413f (patch)
tree9228f807ef88168b2dd12978f5cd8e98f5918b52
parenta9798a359a2e3739fa86e28dcaf647aa61a1620d (diff)
parent20df0019f1af926b838ef548ec22a9c809537b70 (diff)
downloadnextcloud-server-74f31bac8c0473f3dc92fcb54967f4cf977c413f.tar.gz
nextcloud-server-74f31bac8c0473f3dc92fcb54967f4cf977c413f.zip
Merge pull request #37609 from nextcloud/showTags
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php1
-rw-r--r--apps/dav/composer/composer/autoload_static.php1
-rw-r--r--apps/dav/lib/Server.php6
-rw-r--r--apps/dav/lib/SystemTag/SystemTagList.php73
-rw-r--r--apps/dav/lib/SystemTag/SystemTagMappingNode.php5
-rw-r--r--apps/dav/lib/SystemTag/SystemTagNode.php9
-rw-r--r--apps/dav/lib/SystemTag/SystemTagPlugin.php107
-rw-r--r--apps/dav/lib/SystemTag/SystemTagsByIdCollection.php25
-rw-r--r--apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php22
-rw-r--r--apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php18
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php19
-rw-r--r--lib/public/SystemTag/ISystemTagManager.php4
12 files changed, 265 insertions, 25 deletions
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 6745ffe41b4..db7de8c9ac6 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -304,6 +304,7 @@ return array(
'OCA\\DAV\\Settings\\AvailabilitySettings' => $baseDir . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php',
'OCA\\DAV\\Storage\\PublicOwnerWrapper' => $baseDir . '/../lib/Storage/PublicOwnerWrapper.php',
+ 'OCA\\DAV\\SystemTag\\SystemTagList' => $baseDir . '/../lib/SystemTag/SystemTagList.php',
'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => $baseDir . '/../lib/SystemTag/SystemTagMappingNode.php',
'OCA\\DAV\\SystemTag\\SystemTagNode' => $baseDir . '/../lib/SystemTag/SystemTagNode.php',
'OCA\\DAV\\SystemTag\\SystemTagPlugin' => $baseDir . '/../lib/SystemTag/SystemTagPlugin.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 302a424d08e..c29d93d72a8 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -319,6 +319,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Settings\\AvailabilitySettings' => __DIR__ . '/..' . '/../lib/Settings/AvailabilitySettings.php',
'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php',
'OCA\\DAV\\Storage\\PublicOwnerWrapper' => __DIR__ . '/..' . '/../lib/Storage/PublicOwnerWrapper.php',
+ 'OCA\\DAV\\SystemTag\\SystemTagList' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagList.php',
'OCA\\DAV\\SystemTag\\SystemTagMappingNode' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagMappingNode.php',
'OCA\\DAV\\SystemTag\\SystemTagNode' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagNode.php',
'OCA\\DAV\\SystemTag\\SystemTagPlugin' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagPlugin.php',
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 4be149ac440..909bcaa71e8 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -208,11 +208,7 @@ class Server {
}
// system tags plugins
- $this->server->addPlugin(new SystemTagPlugin(
- \OC::$server->getSystemTagManager(),
- \OC::$server->getGroupManager(),
- \OC::$server->getUserSession()
- ));
+ $this->server->addPlugin(\OC::$server->get(SystemTagPlugin::class));
// comments plugin
$this->server->addPlugin(new CommentsPlugin(
diff --git a/apps/dav/lib/SystemTag/SystemTagList.php b/apps/dav/lib/SystemTag/SystemTagList.php
new file mode 100644
index 00000000000..678c8042a39
--- /dev/null
+++ b/apps/dav/lib/SystemTag/SystemTagList.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * @copyright Copyright (c) 2023 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ */
+namespace OCA\DAV\SystemTag;
+
+use OCP\IUser;
+use OCP\SystemTag\ISystemTag;
+use OCP\SystemTag\ISystemTagManager;
+use Sabre\Xml\Element;
+use Sabre\Xml\Reader;
+use Sabre\Xml\Writer;
+
+/**
+ * TagList property
+ *
+ * This property contains multiple "tag" elements, each containing a tag name.
+ */
+class SystemTagList implements Element {
+ public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
+
+ /** @var ISystemTag[] */
+ private array $tags;
+ private ISystemTagManager $tagManager;
+ private IUser $user;
+
+ public function __construct(array $tags, ISystemTagManager $tagManager, IUser $user) {
+ $this->tags = $tags;
+ $this->tagManager = $tagManager;
+ $this->user = $user;
+ }
+
+ /**
+ * @return ISystemTag[]
+ */
+ public function getTags(): array {
+ return $this->tags;
+ }
+
+ public static function xmlDeserialize(Reader $reader): void {
+ // unsupported/unused
+ }
+
+ public function xmlSerialize(Writer $writer): void {
+ foreach ($this->tags as $tag) {
+ $writer->startElement('{' . self::NS_NEXTCLOUD . '}system-tag');
+ $writer->writeAttributes([
+ SystemTagPlugin::CANASSIGN_PROPERTYNAME => $this->tagManager->canUserAssignTag($tag, $this->user) ? 'true' : 'false',
+ SystemTagPlugin::ID_PROPERTYNAME => $tag->getId(),
+ SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME => $tag->isUserAssignable() ? 'true' : 'false',
+ SystemTagPlugin::USERVISIBLE_PROPERTYNAME => $tag->isUserVisible() ? 'true' : 'false',
+ ]);
+ $writer->write($tag->getName());
+ $writer->endElement();
+ }
+ }
+}
diff --git a/apps/dav/lib/SystemTag/SystemTagMappingNode.php b/apps/dav/lib/SystemTag/SystemTagMappingNode.php
index 344ff1dbc70..9762b6e1db9 100644
--- a/apps/dav/lib/SystemTag/SystemTagMappingNode.php
+++ b/apps/dav/lib/SystemTag/SystemTagMappingNode.php
@@ -137,6 +137,8 @@ class SystemTagMappingNode implements \Sabre\DAV\INode {
* @param string $name The new name
*
* @throws MethodNotAllowed not allowed to rename node
+ *
+ * @return never
*/
public function setName($name) {
throw new MethodNotAllowed();
@@ -145,6 +147,7 @@ class SystemTagMappingNode implements \Sabre\DAV\INode {
/**
* Returns null, not supported
*
+ * @return null
*/
public function getLastModified() {
return null;
@@ -152,6 +155,8 @@ class SystemTagMappingNode implements \Sabre\DAV\INode {
/**
* Delete tag to object association
+ *
+ * @return void
*/
public function delete() {
try {
diff --git a/apps/dav/lib/SystemTag/SystemTagNode.php b/apps/dav/lib/SystemTag/SystemTagNode.php
index a31deb59a93..7310cdb19a2 100644
--- a/apps/dav/lib/SystemTag/SystemTagNode.php
+++ b/apps/dav/lib/SystemTag/SystemTagNode.php
@@ -103,6 +103,8 @@ class SystemTagNode implements \Sabre\DAV\INode {
* @param string $name The new name
*
* @throws MethodNotAllowed not allowed to rename node
+ *
+ * @return never
*/
public function setName($name) {
throw new MethodNotAllowed();
@@ -114,11 +116,12 @@ class SystemTagNode implements \Sabre\DAV\INode {
* @param string $name new tag name
* @param bool $userVisible user visible
* @param bool $userAssignable user assignable
+ *
* @throws NotFound whenever the given tag id does not exist
* @throws Forbidden whenever there is no permission to update said tag
* @throws Conflict whenever a tag already exists with the given attributes
*/
- public function update($name, $userVisible, $userAssignable) {
+ public function update($name, $userVisible, $userAssignable): void {
try {
if (!$this->tagManager->canUserSeeTag($this->tag, $this->user)) {
throw new NotFound('Tag with id ' . $this->tag->getId() . ' does not exist');
@@ -151,11 +154,15 @@ class SystemTagNode implements \Sabre\DAV\INode {
/**
* Returns null, not supported
*
+ * @return null
*/
public function getLastModified() {
return null;
}
+ /**
+ * @return void
+ */
public function delete() {
try {
if (!$this->isAdmin) {
diff --git a/apps/dav/lib/SystemTag/SystemTagPlugin.php b/apps/dav/lib/SystemTag/SystemTagPlugin.php
index c21935edfdc..c5c828cfbff 100644
--- a/apps/dav/lib/SystemTag/SystemTagPlugin.php
+++ b/apps/dav/lib/SystemTag/SystemTagPlugin.php
@@ -25,10 +25,14 @@
*/
namespace OCA\DAV\SystemTag;
+use OCA\DAV\Connector\Sabre\Directory;
+use OCA\DAV\Connector\Sabre\Node;
use OCP\IGroupManager;
+use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Exception\Conflict;
@@ -56,6 +60,7 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
public const USERASSIGNABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-assignable';
public const GROUPS_PROPERTYNAME = '{http://owncloud.org/ns}groups';
public const CANASSIGN_PROPERTYNAME = '{http://owncloud.org/ns}can-assign';
+ public const SYSTEM_TAGS_PROPERTYNAME = '{http://nextcloud.org/ns}system-tags';
/**
* @var \Sabre\DAV\Server $server
@@ -77,17 +82,23 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
*/
protected $groupManager;
- /**
- * @param ISystemTagManager $tagManager tag manager
- * @param IGroupManager $groupManager
- * @param IUserSession $userSession
- */
- public function __construct(ISystemTagManager $tagManager,
- IGroupManager $groupManager,
- IUserSession $userSession) {
+ /** @var array<int, string[]> */
+ private array $cachedTagMappings = [];
+ /** @var array<string, ISystemTag> */
+ private array $cachedTags = [];
+
+ private ISystemTagObjectMapper $tagMapper;
+
+ public function __construct(
+ ISystemTagManager $tagManager,
+ IGroupManager $groupManager,
+ IUserSession $userSession,
+ ISystemTagObjectMapper $tagMapper,
+ ) {
$this->tagManager = $tagManager;
$this->userSession = $userSession;
$this->groupManager = $groupManager;
+ $this->tagMapper = $tagMapper;
}
/**
@@ -215,11 +226,18 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
*
* @param PropFind $propFind
* @param \Sabre\DAV\INode $node
+ *
+ * @return void
*/
public function handleGetProperties(
PropFind $propFind,
\Sabre\DAV\INode $node
) {
+ if ($node instanceof Node) {
+ $this->propfindForFile($propFind, $node);
+ return;
+ }
+
if (!($node instanceof SystemTagNode) && !($node instanceof SystemTagMappingNode)) {
return;
}
@@ -260,6 +278,79 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin {
});
}
+ private function propfindForFile(PropFind $propFind, Node $node): void {
+ if ($node instanceof Directory
+ && $propFind->getDepth() !== 0
+ && !is_null($propFind->getStatus(self::SYSTEM_TAGS_PROPERTYNAME))) {
+ $fileIds = [$node->getId()];
+
+ // note: pre-fetching only supported for depth <= 1
+ $folderContent = $node->getNode()->getDirectoryListing();
+ foreach ($folderContent as $info) {
+ $fileIds[] = $info->getId();
+ }
+
+ $tags = $this->tagMapper->getTagIdsForObjects($fileIds, 'files');
+
+ $this->cachedTagMappings = $this->cachedTagMappings + $tags;
+ $emptyFileIds = array_diff($fileIds, array_keys($tags));
+
+ // also cache the ones that were not found
+ foreach ($emptyFileIds as $fileId) {
+ $this->cachedTagMappings[$fileId] = [];
+ }
+ }
+
+ $propFind->handle(self::SYSTEM_TAGS_PROPERTYNAME, function () use ($node) {
+ $user = $this->userSession->getUser();
+ if ($user === null) {
+ return;
+ }
+
+ $tags = $this->getTagsForFile($node->getId(), $user);
+ return new SystemTagList($tags, $this->tagManager, $user);
+ });
+ }
+
+ /**
+ * @param int $fileId
+ * @return ISystemTag[]
+ */
+ private function getTagsForFile(int $fileId, IUser $user): array {
+
+ if (isset($this->cachedTagMappings[$fileId])) {
+ $tagIds = $this->cachedTagMappings[$fileId];
+ } else {
+ $tags = $this->tagMapper->getTagIdsForObjects([$fileId], 'files');
+ $fileTags = current($tags);
+ if ($fileTags) {
+ $tagIds = $fileTags;
+ } else {
+ $tagIds = [];
+ }
+ }
+
+ $tags = array_filter(array_map(function(string $tagId) {
+ return $this->cachedTags[$tagId] ?? null;
+ }, $tagIds));
+
+ $uncachedTagIds = array_filter($tagIds, function(string $tagId): bool {
+ return !isset($this->cachedTags[$tagId]);
+ });
+
+ if (count($uncachedTagIds)) {
+ $retrievedTags = $this->tagManager->getTagsByIds($uncachedTagIds);
+ foreach ($retrievedTags as $tag) {
+ $this->cachedTags[$tag->getId()] = $tag;
+ }
+ $tags += $retrievedTags;
+ }
+
+ return array_filter($tags, function(ISystemTag $tag) use ($user) {
+ return $this->tagManager->canUserSeeTag($tag, $user);
+ });
+ }
+
/**
* Updates tag attributes
*
diff --git a/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php b/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php
index 1256c58921e..86ccadf5f56 100644
--- a/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php
+++ b/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php
@@ -84,7 +84,10 @@ class SystemTagsByIdCollection implements ICollection {
/**
* @param string $name
* @param resource|string $data Initial payload
+ *
* @throws Forbidden
+ *
+ * @return never
*/
public function createFile($name, $data = null) {
throw new Forbidden('Cannot create tags by id');
@@ -92,6 +95,8 @@ class SystemTagsByIdCollection implements ICollection {
/**
* @param string $name
+ *
+ * @return never
*/
public function createDirectory($name) {
throw new Forbidden('Permission denied to create collections');
@@ -99,6 +104,8 @@ class SystemTagsByIdCollection implements ICollection {
/**
* @param string $name
+ *
+ * @return SystemTagNode
*/
public function getChild($name) {
try {
@@ -115,6 +122,11 @@ class SystemTagsByIdCollection implements ICollection {
}
}
+ /**
+ * @return SystemTagNode[]
+ *
+ * @psalm-return array<SystemTagNode>
+ */
public function getChildren() {
$visibilityFilter = true;
if ($this->isAdmin()) {
@@ -145,14 +157,25 @@ class SystemTagsByIdCollection implements ICollection {
}
}
+ /**
+ * @return never
+ */
public function delete() {
throw new Forbidden('Permission denied to delete this collection');
}
+ /**
+ * @return string
+ *
+ * @psalm-return 'systemtags'
+ */
public function getName() {
return 'systemtags';
}
+ /**
+ * @return never
+ */
public function setName($name) {
throw new Forbidden('Permission denied to rename this collection');
}
@@ -160,7 +183,7 @@ class SystemTagsByIdCollection implements ICollection {
/**
* Returns the last modification time, as a unix timestamp
*
- * @return int
+ * @return null
*/
public function getLastModified() {
return null;
diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php b/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php
index 8bb34182b0c..4d73c17d7dd 100644
--- a/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php
+++ b/apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php
@@ -92,6 +92,9 @@ class SystemTagsObjectMappingCollection implements ICollection {
$this->user = $user;
}
+ /**
+ * @return void
+ */
public function createFile($name, $data = null) {
$tagId = $name;
try {
@@ -110,10 +113,16 @@ class SystemTagsObjectMappingCollection implements ICollection {
}
}
+ /**
+ * @return never
+ */
public function createDirectory($name) {
throw new Forbidden('Permission denied to create collections');
}
+ /**
+ * @return SystemTagMappingNode
+ */
public function getChild($tagName) {
try {
if ($this->tagMapper->haveTag([$this->objectId], $this->objectType, $tagName, true)) {
@@ -131,6 +140,11 @@ class SystemTagsObjectMappingCollection implements ICollection {
}
}
+ /**
+ * @return SystemTagMappingNode[]
+ *
+ * @psalm-return list<SystemTagMappingNode>
+ */
public function getChildren() {
$tagIds = current($this->tagMapper->getTagIdsForObjects([$this->objectId], $this->objectType));
if (empty($tagIds)) {
@@ -168,6 +182,9 @@ class SystemTagsObjectMappingCollection implements ICollection {
}
}
+ /**
+ * @return never
+ */
public function delete() {
throw new Forbidden('Permission denied to delete this collection');
}
@@ -176,6 +193,9 @@ class SystemTagsObjectMappingCollection implements ICollection {
return $this->objectId;
}
+ /**
+ * @return never
+ */
public function setName($name) {
throw new Forbidden('Permission denied to rename this collection');
}
@@ -183,7 +203,7 @@ class SystemTagsObjectMappingCollection implements ICollection {
/**
* Returns the last modification time, as a unix timestamp
*
- * @return int
+ * @return null
*/
public function getLastModified() {
return null;
diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
index 1ca45c32ce4..3fa40278cdb 100644
--- a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
+++ b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
@@ -98,7 +98,9 @@ class SystemTagsObjectTypeCollection implements ICollection {
/**
* @param string $name
* @param resource|string $data Initial payload
- * @return null|string
+ *
+ * @return never
+ *
* @throws Forbidden
*/
public function createFile($name, $data = null) {
@@ -107,7 +109,10 @@ class SystemTagsObjectTypeCollection implements ICollection {
/**
* @param string $name
+ *
* @throws Forbidden
+ *
+ * @return never
*/
public function createDirectory($name) {
throw new Forbidden('Permission denied to create collections');
@@ -133,6 +138,9 @@ class SystemTagsObjectTypeCollection implements ICollection {
);
}
+ /**
+ * @return never
+ */
public function getChildren() {
// do not list object ids
throw new MethodNotAllowed();
@@ -148,6 +156,9 @@ class SystemTagsObjectTypeCollection implements ICollection {
return call_user_func($this->childExistsFunction, $name);
}
+ /**
+ * @return never
+ */
public function delete() {
throw new Forbidden('Permission denied to delete this collection');
}
@@ -158,7 +169,10 @@ class SystemTagsObjectTypeCollection implements ICollection {
/**
* @param string $name
+ *
* @throws Forbidden
+ *
+ * @return never
*/
public function setName($name) {
throw new Forbidden('Permission denied to rename this collection');
@@ -167,7 +181,7 @@ class SystemTagsObjectTypeCollection implements ICollection {
/**
* Returns the last modification time, as a unix timestamp
*
- * @return int
+ * @return null
*/
public function getLastModified() {
return null;
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
index 291aa45ad0e..8341c6ca009 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
@@ -36,6 +36,7 @@ use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
@@ -84,6 +85,11 @@ class SystemTagPluginTest extends \Test\TestCase {
*/
private $plugin;
+ /**
+ * @var ISystemTagObjectMapper
+ */
+ private $tagMapper;
+
protected function setUp(): void {
parent::setUp();
$this->tree = $this->getMockBuilder(Tree::class)
@@ -108,11 +114,14 @@ class SystemTagPluginTest extends \Test\TestCase {
->expects($this->any())
->method('isLoggedIn')
->willReturn(true);
+ $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
+ ->getMock();
$this->plugin = new \OCA\DAV\SystemTag\SystemTagPlugin(
$this->tagManager,
$this->groupManager,
- $this->userSession
+ $this->userSession,
+ $this->tagMapper
);
$this->plugin->initialize($this->server);
}
@@ -233,7 +242,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->assertEquals($expectedProperties, $result[200]);
}
-
+
public function testGetPropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -330,7 +339,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->assertEquals(200, $result[self::USERVISIBLE_PROPERTYNAME]);
}
-
+
public function testUpdatePropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -537,7 +546,7 @@ class SystemTagPluginTest extends \Test\TestCase {
->method('createTag')
->with('Test', $userVisible, $userAssignable)
->willReturn($systemTag);
-
+
if (!empty($groups)) {
$this->tagManager->expects($this->once())
->method('setTagGroups')
@@ -658,7 +667,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateTagToUnknownNode(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
diff --git a/lib/public/SystemTag/ISystemTagManager.php b/lib/public/SystemTag/ISystemTagManager.php
index 9918e3a4f99..1cf7263b456 100644
--- a/lib/public/SystemTag/ISystemTagManager.php
+++ b/lib/public/SystemTag/ISystemTagManager.php
@@ -125,7 +125,7 @@ interface ISystemTagManager {
* @param ISystemTag $tag tag to check permission for
* @param IUser $user user to check permission for
*
- * @return true if the user is allowed to assign/unassign the tag, false otherwise
+ * @return bool true if the user is allowed to assign/unassign the tag, false otherwise
*
* @since 9.1.0
*/
@@ -137,7 +137,7 @@ interface ISystemTagManager {
* @param ISystemTag $tag tag to check permission for
* @param IUser $user user to check permission for
*
- * @return true if the user can see the tag, false otherwise
+ * @return bool true if the user can see the tag, false otherwise
*
* @since 9.1.0
*/