diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 2e878decb3f96..34adfd28e4f9c 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -361,6 +361,7 @@ '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\\SystemTagObjectType' => $baseDir . '/../lib/SystemTag/SystemTagObjectType.php', 'OCA\\DAV\\SystemTag\\SystemTagPlugin' => $baseDir . '/../lib/SystemTag/SystemTagPlugin.php', 'OCA\\DAV\\SystemTag\\SystemTagsByIdCollection' => $baseDir . '/../lib/SystemTag/SystemTagsByIdCollection.php', 'OCA\\DAV\\SystemTag\\SystemTagsInUseCollection' => $baseDir . '/../lib/SystemTag/SystemTagsInUseCollection.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 5f43453cda6a7..883b1fc710c4d 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -376,6 +376,7 @@ class ComposerStaticInitDAV '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\\SystemTagObjectType' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagObjectType.php', 'OCA\\DAV\\SystemTag\\SystemTagPlugin' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagPlugin.php', 'OCA\\DAV\\SystemTag\\SystemTagsByIdCollection' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagsByIdCollection.php', 'OCA\\DAV\\SystemTag\\SystemTagsInUseCollection' => __DIR__ . '/..' . '/../lib/SystemTag/SystemTagsInUseCollection.php', diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index 6ede8cb683c17..751ab17bb7aa6 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -105,11 +105,7 @@ public function __construct() { $publicCalendarRoot = new PublicCalendarRoot($caldavBackend, $l10n, $config, $logger); - $systemTagCollection = new SystemTagsByIdCollection( - \OC::$server->getSystemTagManager(), - \OC::$server->getUserSession(), - $groupManager - ); + $systemTagCollection = Server::get(SystemTagsByIdCollection::class); $systemTagRelationsCollection = new SystemTagsRelationsCollection( \OC::$server->getSystemTagManager(), \OC::$server->getSystemTagObjectMapper(), diff --git a/apps/dav/lib/SystemTag/SystemTagNode.php b/apps/dav/lib/SystemTag/SystemTagNode.php index 06eead814b27b..ce84e66813bfd 100644 --- a/apps/dav/lib/SystemTag/SystemTagNode.php +++ b/apps/dav/lib/SystemTag/SystemTagNode.php @@ -10,8 +10,8 @@ use OCP\IUser; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagAlreadyExistsException; - use OCP\SystemTag\TagNotFoundException; use Sabre\DAV\Exception\Conflict; use Sabre\DAV\Exception\Forbidden; @@ -21,31 +21,7 @@ /** * DAV node representing a system tag, with the name being the tag id. */ -class SystemTagNode implements \Sabre\DAV\INode { - - /** - * @var ISystemTag - */ - protected $tag; - - /** - * @var ISystemTagManager - */ - protected $tagManager; - - /** - * User - * - * @var IUser - */ - protected $user; - - /** - * Whether to allow permissions for admins - * - * @var bool - */ - protected $isAdmin; +class SystemTagNode implements \Sabre\DAV\ICollection { protected int $numberOfFiles = -1; protected int $referenceFileId = -1; @@ -58,11 +34,13 @@ class SystemTagNode implements \Sabre\DAV\INode { * @param bool $isAdmin whether to allow operations for admins * @param ISystemTagManager $tagManager tag manager */ - public function __construct(ISystemTag $tag, IUser $user, $isAdmin, ISystemTagManager $tagManager) { - $this->tag = $tag; - $this->user = $user; - $this->isAdmin = $isAdmin; - $this->tagManager = $tagManager; + public function __construct( + protected ISystemTag $tag, + protected IUser $user, + protected bool $isAdmin, + protected ISystemTagManager $tagManager, + protected ISystemTagObjectMapper $tagMapper, + ) { } /** @@ -181,4 +159,26 @@ public function getReferenceFileId(): int { public function setReferenceFileId(int $referenceFileId): void { $this->referenceFileId = $referenceFileId; } + + public function createFile($name, $data = null) { + throw new MethodNotAllowed(); + } + + public function createDirectory($name) { + throw new MethodNotAllowed(); + } + + public function getChild($name) { + return new SystemTagObjectType($this->tag, $name, $this->tagManager, $this->tagMapper); + } + + public function childExists($name) { + $objectTypes = $this->tagMapper->getAvailableObjectTypes(); + return in_array($name, $objectTypes); + } + + public function getChildren() { + // We currently don't have a method to list allowed tag mappings types + return [new SystemTagObjectType($this->tag, 'files', $this->tagManager, $this->tagMapper)]; + } } diff --git a/apps/dav/lib/SystemTag/SystemTagObjectType.php b/apps/dav/lib/SystemTag/SystemTagObjectType.php new file mode 100644 index 0000000000000..53686a3e76426 --- /dev/null +++ b/apps/dav/lib/SystemTag/SystemTagObjectType.php @@ -0,0 +1,58 @@ +objectsIds)) { + $this->objectsIds = $this->tagMapper->getObjectIdsForTags($this->tag->getId(), $this->type); + } + + return $this->objectsIds; + } + + public function delete() { + throw new MethodNotAllowed(); + } + + public function getName() { + return $this->type; + } + + public function setName($name) { + throw new MethodNotAllowed(); + } + + public function getLastModified() { + return null; + } +} diff --git a/apps/dav/lib/SystemTag/SystemTagPlugin.php b/apps/dav/lib/SystemTag/SystemTagPlugin.php index 6098a41ab3b0d..f575989d893c1 100644 --- a/apps/dav/lib/SystemTag/SystemTagPlugin.php +++ b/apps/dav/lib/SystemTag/SystemTagPlugin.php @@ -37,6 +37,7 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { // namespace public const NS_OWNCLOUD = 'http://owncloud.org/ns'; + public const NS_NEXTCLOUD = 'http://nextcloud.org/ns'; public const ID_PROPERTYNAME = '{http://owncloud.org/ns}id'; public const DISPLAYNAME_PROPERTYNAME = '{http://owncloud.org/ns}display-name'; public const USERVISIBLE_PROPERTYNAME = '{http://owncloud.org/ns}user-visible'; @@ -45,7 +46,8 @@ class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { public const CANASSIGN_PROPERTYNAME = '{http://owncloud.org/ns}can-assign'; public const SYSTEM_TAGS_PROPERTYNAME = '{http://nextcloud.org/ns}system-tags'; public const NUM_FILES_PROPERTYNAME = '{http://nextcloud.org/ns}files-assigned'; - public const FILEID_PROPERTYNAME = '{http://nextcloud.org/ns}reference-fileid'; + public const REFERENCE_FILEID_PROPERTYNAME = '{http://nextcloud.org/ns}reference-fileid'; + public const OBJECTID_PROPERTYNAME = '{http://nextcloud.org/ns}object-id'; /** * @var \Sabre\DAV\Server $server @@ -223,7 +225,7 @@ public function handleGetProperties( return; } - if (!($node instanceof SystemTagNode) && !($node instanceof SystemTagMappingNode)) { + if (!($node instanceof SystemTagNode) && !($node instanceof SystemTagMappingNode) && !($node instanceof SystemTagObjectType)) { return; } @@ -272,10 +274,16 @@ public function handleGetProperties( return $node->getNumberOfFiles(); }); - $propFind->handle(self::FILEID_PROPERTYNAME, function () use ($node): int { + $propFind->handle(self::REFERENCE_FILEID_PROPERTYNAME, function () use ($node): int { return $node->getReferenceFileId(); }); } + + if ($node instanceof SystemTagObjectType) { + $propFind->handle(self::OBJECTID_PROPERTYNAME, function () use ($node) { + return $node->getObjectsIds(); + }); + } } private function propfindForFile(PropFind $propFind, Node $node): void { @@ -372,7 +380,7 @@ public function handleUpdateProperties($path, PropPatch $propPatch) { self::USERASSIGNABLE_PROPERTYNAME, self::GROUPS_PROPERTYNAME, self::NUM_FILES_PROPERTYNAME, - self::FILEID_PROPERTYNAME, + self::REFERENCE_FILEID_PROPERTYNAME, ], function ($props) use ($node) { $tag = $node->getSystemTag(); $name = $tag->getName(); @@ -409,7 +417,7 @@ public function handleUpdateProperties($path, PropPatch $propPatch) { $this->tagManager->setTagGroups($tag, $groupIds); } - if (isset($props[self::NUM_FILES_PROPERTYNAME]) || isset($props[self::FILEID_PROPERTYNAME])) { + if (isset($props[self::NUM_FILES_PROPERTYNAME]) || isset($props[self::REFERENCE_FILEID_PROPERTYNAME])) { // read-only properties throw new Forbidden(); } diff --git a/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php b/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php index 13e79c99b65a8..b854db7b94db5 100644 --- a/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php +++ b/apps/dav/lib/SystemTag/SystemTagsByIdCollection.php @@ -11,6 +11,7 @@ use OCP\IUserSession; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagNotFoundException; use Sabre\DAV\Exception\BadRequest; use Sabre\DAV\Exception\Forbidden; @@ -19,21 +20,6 @@ class SystemTagsByIdCollection implements ICollection { - /** - * @var ISystemTagManager - */ - private $tagManager; - - /** - * @var IGroupManager - */ - private $groupManager; - - /** - * @var IUserSession - */ - private $userSession; - /** * SystemTagsByIdCollection constructor. * @@ -42,13 +28,11 @@ class SystemTagsByIdCollection implements ICollection { * @param IGroupManager $groupManager */ public function __construct( - ISystemTagManager $tagManager, - IUserSession $userSession, - IGroupManager $groupManager, + private ISystemTagManager $tagManager, + private IUserSession $userSession, + private IGroupManager $groupManager, + protected ISystemTagObjectMapper $tagMapper, ) { - $this->tagManager = $tagManager; - $this->userSession = $userSession; - $this->groupManager = $groupManager; } /** @@ -180,6 +164,6 @@ public function getLastModified() { * @return SystemTagNode */ private function makeNode(ISystemTag $tag) { - return new SystemTagNode($tag, $this->userSession->getUser(), $this->isAdmin(), $this->tagManager); + return new SystemTagNode($tag, $this->userSession->getUser(), $this->isAdmin(), $this->tagManager, $this->tagMapper); } } diff --git a/apps/dav/lib/SystemTag/SystemTagsInUseCollection.php b/apps/dav/lib/SystemTag/SystemTagsInUseCollection.php index 0431acc553af8..81abc6c156969 100644 --- a/apps/dav/lib/SystemTag/SystemTagsInUseCollection.php +++ b/apps/dav/lib/SystemTag/SystemTagsInUseCollection.php @@ -16,24 +16,21 @@ use OCP\Files\NotPermittedException; use OCP\IUserSession; use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\SimpleCollection; class SystemTagsInUseCollection extends SimpleCollection { - protected IUserSession $userSession; - protected IRootFolder $rootFolder; - protected string $mediaType; - protected ISystemTagManager $systemTagManager; - protected SystemTagsInFilesDetector $systemTagsInFilesDetector; /** @noinspection PhpMissingParentConstructorInspection */ public function __construct( - IUserSession $userSession, - IRootFolder $rootFolder, - ISystemTagManager $systemTagManager, - SystemTagsInFilesDetector $systemTagsInFilesDetector, - string $mediaType = '', + protected IUserSession $userSession, + protected IRootFolder $rootFolder, + protected ISystemTagManager $systemTagManager, + protected ISystemTagObjectMapper $tagMapper, + protected SystemTagsInFilesDetector $systemTagsInFilesDetector, + protected string $mediaType = '', ) { $this->userSession = $userSession; $this->rootFolder = $rootFolder; @@ -54,7 +51,7 @@ public function getChild($name): self { if ($this->mediaType !== '') { throw new NotFound('Invalid media type'); } - return new self($this->userSession, $this->rootFolder, $this->systemTagManager, $this->systemTagsInFilesDetector, $name); + return new self($this->userSession, $this->rootFolder, $this->systemTagManager, $this->tagMapper, $this->systemTagsInFilesDetector, $name); } /** @@ -81,7 +78,7 @@ public function getChildren(): array { foreach ($result as $tagData) { $tag = new SystemTag((string)$tagData['id'], $tagData['name'], (bool)$tagData['visibility'], (bool)$tagData['editable']); // read only, so we can submit the isAdmin parameter as false generally - $node = new SystemTagNode($tag, $user, false, $this->systemTagManager); + $node = new SystemTagNode($tag, $user, false, $this->systemTagManager, $this->tagMapper); $node->setNumberOfFiles((int)$tagData['number_files']); $node->setReferenceFileId((int)$tagData['ref_file_id']); $children[] = $node; diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php index 2ffbc1cf01fda..e30d8f73b6a46 100644 --- a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php +++ b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php @@ -13,7 +13,9 @@ use OCP\IUser; use OCP\IUserSession; use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\TagNotFoundException; +use PHPUnit\Framework\MockObject\MockObject; class SystemTagsByIdCollectionTest extends \Test\TestCase { @@ -40,21 +42,31 @@ public function getNode($isAdmin = true) { $this->user->expects($this->any()) ->method('getUID') ->willReturn('testuser'); + + /** @var IUserSession|MockObject */ $userSession = $this->getMockBuilder(IUserSession::class) ->getMock(); $userSession->expects($this->any()) ->method('getUser') ->willReturn($this->user); + + /** @var IGroupManager|MockObject */ $groupManager = $this->getMockBuilder(IGroupManager::class) ->getMock(); $groupManager->expects($this->any()) ->method('isAdmin') ->with('testuser') ->willReturn($isAdmin); + + /** @var ISystemTagObjectMapper|MockObject */ + $tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class) + ->getMock(); + return new SystemTagsByIdCollection( $this->tagManager, $userSession, - $groupManager + $groupManager, + $tagMapper, ); }