diff --git a/apps/files/lib/Helper.php b/apps/files/lib/Helper.php index 82d1cc9493492..b1439ac7fa508 100644 --- a/apps/files/lib/Helper.php +++ b/apps/files/lib/Helper.php @@ -9,66 +9,12 @@ use OC\Files\Filesystem; use OCP\Files\FileInfo; -use OCP\Files\IMimeTypeDetector; -use OCP\Files\NotFoundException; -use OCP\ITagManager; -use OCP\Server; use OCP\Util; /** * Helper class for manipulating file information */ class Helper { - /** - * @param string $dir - * @return array - * @throws NotFoundException - */ - public static function buildFileStorageStatistics($dir) { - // information about storage capacities - $storageInfo = \OC_Helper::getStorageInfo($dir); - $l = Util::getL10N('files'); - $maxUploadFileSize = Util::maxUploadFilesize($dir, $storageInfo['free']); - $maxHumanFileSize = Util::humanFileSize($maxUploadFileSize); - $maxHumanFileSize = $l->t('Upload (max. %s)', [$maxHumanFileSize]); - - return [ - 'uploadMaxFilesize' => $maxUploadFileSize, - 'maxHumanFilesize' => $maxHumanFileSize, - 'freeSpace' => $storageInfo['free'], - 'quota' => $storageInfo['quota'], - 'total' => $storageInfo['total'], - 'used' => $storageInfo['used'], - 'usedSpacePercent' => $storageInfo['relative'], - 'owner' => $storageInfo['owner'], - 'ownerDisplayName' => $storageInfo['ownerDisplayName'], - 'mountType' => $storageInfo['mountType'], - 'mountPoint' => $storageInfo['mountPoint'], - ]; - } - - /** - * Determine icon for a given file - * - * @param FileInfo $file file info - * @return string icon URL - */ - public static function determineIcon($file) { - if ($file['type'] === 'dir') { - $icon = Server::get(IMimeTypeDetector::class)->mimeTypeIcon('dir'); - // TODO: move this part to the client side, using mountType - if ($file->isShared()) { - $icon = Server::get(IMimeTypeDetector::class)->mimeTypeIcon('dir-shared'); - } elseif ($file->isMounted()) { - $icon = Server::get(IMimeTypeDetector::class)->mimeTypeIcon('dir-external'); - } - } else { - $icon = Server::get(IMimeTypeDetector::class)->mimeTypeIcon($file->getMimetype()); - } - - return substr($icon, 0, -3) . 'svg'; - } - /** * Comparator function to sort files alphabetically and have * the directories appear first @@ -161,20 +107,6 @@ public static function formatFileInfo(FileInfo $i) { return $entry; } - /** - * Format file info for JSON - * @param FileInfo[] $fileInfos file infos - * @return array - */ - public static function formatFileInfos($fileInfos) { - $files = []; - foreach ($fileInfos as $i) { - $files[] = self::formatFileInfo($i); - } - - return $files; - } - /** * Retrieves the contents of the given directory and * returns it as a sorted array of FileInfo. @@ -191,43 +123,6 @@ public static function getFiles($dir, $sortAttribute = 'name', $sortDescending = return self::sortFiles($content, $sortAttribute, $sortDescending); } - /** - * Populate the result set with file tags - * - * @psalm-template T of array{tags?: list, file_source: int, ...array} - * @param list $fileList - * @return list file list populated with tags - */ - public static function populateTags(array $fileList, ITagManager $tagManager) { - $tagger = $tagManager->load('files'); - $tags = $tagger->getTagsForObjects(array_map(static fn (array $fileData) => $fileData['file_source'], $fileList)); - - if (!is_array($tags)) { - throw new \UnexpectedValueException('$tags must be an array'); - } - - // Set empty tag array - foreach ($fileList as &$fileData) { - $fileData['tags'] = []; - } - unset($fileData); - - if (!empty($tags)) { - foreach ($tags as $fileId => $fileTags) { - foreach ($fileList as &$fileData) { - if ($fileId !== $fileData['file_source']) { - continue; - } - - $fileData['tags'] = $fileTags; - } - unset($fileData); - } - } - - return $fileList; - } - /** * Sort the given file info array * diff --git a/apps/files/tests/HelperTest.php b/apps/files/tests/HelperTest.php index 0cf2812f816c3..5900e94215c7c 100644 --- a/apps/files/tests/HelperTest.php +++ b/apps/files/tests/HelperTest.php @@ -2,8 +2,6 @@ use OC\Files\FileInfo; use OCA\Files\Helper; -use OCP\ITagManager; -use OCP\ITags; /** * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors @@ -94,36 +92,4 @@ public function testSortByName(string $sort, bool $sortDescending, array $expect $fileNames ); } - - public function testPopulateTags(): void { - $tagManager = $this->createMock(ITagManager::class); - $tagger = $this->createMock(ITags::class); - - $tagManager->method('load') - ->with('files') - ->willReturn($tagger); - - $data = [ - ['file_source' => 10], - ['file_source' => 22, 'foo' => 'bar'], - ['file_source' => 42, 'x' => 'y'], - ]; - - $tags = [ - 10 => ['tag3'], - 42 => ['tag1', 'tag2'], - ]; - - $tagger->method('getTagsForObjects') - ->with([10, 22, 42]) - ->willReturn($tags); - - $result = Helper::populateTags($data, $tagManager); - - $this->assertSame([ - ['file_source' => 10, 'tags' => ['tag3']], - ['file_source' => 22, 'foo' => 'bar', 'tags' => []], - ['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']], - ], $result); - } } diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 446db0b8fcc97..23ba9da1568d3 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -94,6 +94,7 @@ public function __construct( private LoggerInterface $logger, private IProviderFactory $factory, private IMailer $mailer, + private ITagManager $tagManager, private ?string $userId = null, ) { parent::__construct($appName, $request); @@ -472,7 +473,7 @@ public function getShare(string $id, bool $include_tags = false): DataResponse { $share = $this->formatShare($share); if ($include_tags) { - $share = Helper::populateTags([$share], Server::get(ITagManager::class)); + $share = $this->populateTags([$share]); } else { $share = [$share]; } @@ -847,7 +848,7 @@ private function getSharedWithMe($node, bool $includeTags): array { } if ($includeTags) { - $formatted = Helper::populateTags($formatted, Server::get(ITagManager::class)); + $formatted = $this->populateTags($formatted); } return $formatted; @@ -1100,8 +1101,7 @@ private function getFormattedShares( $formatted = $this->fixMissingDisplayName($formatted); if ($includeTags) { - $formatted = - Helper::populateTags($formatted, Server::get(ITagManager::class)); + $formatted = $this->populateTags($formatted); } return $formatted; @@ -2221,4 +2221,41 @@ public function generateToken(): DataResponse { throw new OCSException($this->l->t('Failed to generate a unique token')); } } + + /** + * Populate the result set with file tags + * + * @psalm-template T of array{tags?: list, file_source: int, ...array} + * @param list $fileList + * @return list file list populated with tags + */ + private function populateTags(array $fileList): array { + $tagger = $this->tagManager->load('files'); + $tags = $tagger->getTagsForObjects(array_map(static fn (array $fileData) => $fileData['file_source'], $fileList)); + + if (!is_array($tags)) { + throw new \UnexpectedValueException('$tags must be an array'); + } + + // Set empty tag array + foreach ($fileList as &$fileData) { + $fileData['tags'] = []; + } + unset($fileData); + + if (!empty($tags)) { + foreach ($tags as $fileId => $fileTags) { + foreach ($fileList as &$fileData) { + if ($fileId !== $fileData['file_source']) { + continue; + } + + $fileData['tags'] = $fileTags; + } + unset($fileData); + } + } + + return $fileList; + } } diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 4ef9f536cb9be..a712903d7682b 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -26,6 +26,7 @@ use OCP\IL10N; use OCP\IPreview; use OCP\IRequest; +use OCP\ITagManager; use OCP\IURLGenerator; use OCP\IUserManager; use OCP\Mail\IMailer; @@ -111,6 +112,7 @@ private function createOCS($userId) { $logger = $this->createMock(LoggerInterface::class); $providerFactory = $this->createMock(IProviderFactory::class); $mailer = $this->createMock(IMailer::class); + $tagManager = $this->createMock(ITagManager::class); $dateTimeZone->method('getTimeZone')->willReturn(new \DateTimeZone(date_default_timezone_get())); return new ShareAPIController( @@ -131,6 +133,7 @@ private function createOCS($userId) { $logger, $providerFactory, $mailer, + $tagManager, $userId, ); } diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php index 29eae2dc58129..02c133ee5d18b 100644 --- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php +++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php @@ -28,6 +28,8 @@ use OCP\IL10N; use OCP\IPreview; use OCP\IRequest; +use OCP\ITagManager; +use OCP\ITags; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserManager; @@ -76,6 +78,7 @@ class ShareAPIControllerTest extends TestCase { private LoggerInterface&MockObject $logger; private IProviderFactory&MockObject $factory; private IMailer&MockObject $mailer; + private ITagManager&MockObject $tagManager; protected function setUp(): void { $this->shareManager = $this->createMock(IManager::class); @@ -111,6 +114,7 @@ protected function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); $this->factory = $this->createMock(IProviderFactory::class); $this->mailer = $this->createMock(IMailer::class); + $this->tagManager = $this->createMock(ITagManager::class); $this->ocs = new ShareAPIController( $this->appName, @@ -130,6 +134,7 @@ protected function setUp(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, ); } @@ -157,6 +162,7 @@ private function mockFormatShare() { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, ])->onlyMethods(['formatShare']) ->getMock(); @@ -841,8 +847,8 @@ public function testGetShare(IShare $share, array $result): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ]) ->onlyMethods(['canAccessShare']) ->getMock(); @@ -1474,6 +1480,7 @@ public function testGetShares(array $getSharesParameters, array $shares, array $ $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, ]) ->onlyMethods(['formatShare']) @@ -1816,8 +1823,9 @@ public function testCreateShareUser(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ])->setMethods(['formatShare']) + ])->onlyMethods(['formatShare']) ->getMock(); [$userFolder, $path] = $this->getNonSharedUserFile(); @@ -1913,8 +1921,9 @@ public function testCreateShareGroup(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ])->setMethods(['formatShare']) + ])->onlyMethods(['formatShare']) ->getMock(); $this->request @@ -2338,8 +2347,9 @@ public function testCreateShareRemote(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ])->setMethods(['formatShare']) + ])->onlyMethods(['formatShare']) ->getMock(); [$userFolder, $path] = $this->getNonSharedUserFile(); @@ -2408,8 +2418,9 @@ public function testCreateShareRemoteGroup(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ])->setMethods(['formatShare']) + ])->onlyMethods(['formatShare']) ->getMock(); [$userFolder, $path] = $this->getNonSharedUserFile(); @@ -2639,8 +2650,9 @@ public function testCreateReshareOfFederatedMountNoDeletePermissions(): void { $this->logger, $this->factory, $this->mailer, + $this->tagManager, $this->currentUser, - ])->setMethods(['formatShare']) + ])->onlyMethods(['formatShare']) ->getMock(); $userFolder = $this->getMockBuilder(Folder::class)->getMock(); @@ -5138,4 +5150,30 @@ private function getNonSharedUserFile(): array { $node->method('getId')->willReturn(42); return [$userFolder, $node]; } + + public function testPopulateTags(): void { + $tagger = $this->createMock(ITags::class); + $this->tagManager->method('load') + ->with('files') + ->willReturn($tagger); + $data = [ + ['file_source' => 10], + ['file_source' => 22, 'foo' => 'bar'], + ['file_source' => 42, 'x' => 'y'], + ]; + $tags = [ + 10 => ['tag3'], + 42 => ['tag1', 'tag2'], + ]; + $tagger->method('getTagsForObjects') + ->with([10, 22, 42]) + ->willReturn($tags); + + $result = self::invokePrivate($this->ocs, 'populateTags', [$data]); + $this->assertSame([ + ['file_source' => 10, 'tags' => ['tag3']], + ['file_source' => 22, 'foo' => 'bar', 'tags' => []], + ['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']], + ], $result); + } } diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 8d409314d4d22..c4fb79f395c62 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1396,7 +1396,6 @@ -