diff options
Diffstat (limited to 'apps/files/lib')
-rw-r--r-- | apps/files/lib/Capabilities.php | 4 | ||||
-rw-r--r-- | apps/files/lib/Command/Copy.php | 133 | ||||
-rw-r--r-- | apps/files/lib/Command/Move.php | 122 | ||||
-rw-r--r-- | apps/files/lib/Controller/ApiController.php | 18 | ||||
-rw-r--r-- | apps/files/lib/Controller/DirectEditingController.php | 35 | ||||
-rw-r--r-- | apps/files/lib/Controller/DirectEditingViewController.php | 2 | ||||
-rw-r--r-- | apps/files/lib/Controller/OpenLocalEditorController.php | 18 | ||||
-rw-r--r-- | apps/files/lib/Controller/TemplateController.php | 37 | ||||
-rw-r--r-- | apps/files/lib/Controller/TransferOwnershipController.php | 31 | ||||
-rw-r--r-- | apps/files/lib/Controller/ViewController.php | 5 | ||||
-rw-r--r-- | apps/files/lib/DirectEditingCapabilities.php | 3 | ||||
-rw-r--r-- | apps/files/lib/ResponseDefinitions.php | 67 |
12 files changed, 465 insertions, 10 deletions
diff --git a/apps/files/lib/Capabilities.php b/apps/files/lib/Capabilities.php index 5cb976a47be..dc2aae6acfc 100644 --- a/apps/files/lib/Capabilities.php +++ b/apps/files/lib/Capabilities.php @@ -38,12 +38,14 @@ class Capabilities implements ICapability { /** * Return this classes capabilities + * + * @return array{files: array{bigfilechunking: bool, blacklisted_files: array<mixed>}} */ public function getCapabilities() { return [ 'files' => [ 'bigfilechunking' => true, - 'blacklisted_files' => $this->config->getSystemValue('blacklisted_files', ['.htaccess']) + 'blacklisted_files' => (array)$this->config->getSystemValue('blacklisted_files', ['.htaccess']) ], ]; } diff --git a/apps/files/lib/Command/Copy.php b/apps/files/lib/Command/Copy.php new file mode 100644 index 00000000000..678c82a138f --- /dev/null +++ b/apps/files/lib/Command/Copy.php @@ -0,0 +1,133 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2023 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files\Command; + +use OC\Core\Command\Info\FileUtils; +use OCP\Files\Folder; +use OCP\Files\File; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +class Copy extends Command { + private FileUtils $fileUtils; + + public function __construct(FileUtils $fileUtils) { + $this->fileUtils = $fileUtils; + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('files:copy') + ->setDescription('Copy a file or folder') + ->addArgument('source', InputArgument::REQUIRED, "Source file id or path") + ->addArgument('target', InputArgument::REQUIRED, "Target path") + ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for confirmation and don't output any warnings") + ->addOption('no-target-directory', 'T', InputOption::VALUE_NONE, "When target path is folder, overwrite the folder instead of copying into the folder"); + } + + public function execute(InputInterface $input, OutputInterface $output): int { + $sourceInput = $input->getArgument('source'); + $targetInput = $input->getArgument('target'); + $force = $input->getOption('force'); + $noTargetDir = $input->getOption('no-target-directory'); + + $node = $this->fileUtils->getNode($sourceInput); + $targetNode = $this->fileUtils->getNode($targetInput); + + if (!$node) { + $output->writeln("<error>file $sourceInput not found</error>"); + return 1; + } + + $targetParentPath = dirname(rtrim($targetInput, '/')); + $targetParent = $this->fileUtils->getNode($targetParentPath); + if (!$targetParent) { + $output->writeln("<error>Target parent path $targetParentPath doesn't exist</error>"); + return 1; + } + + $wouldRequireDelete = false; + + if ($targetNode) { + if (!$targetNode->isUpdateable()) { + $output->writeln("<error>$targetInput isn't writable</error>"); + return 1; + } + + if ($targetNode instanceof Folder) { + if ($noTargetDir) { + if (!$force) { + $output->writeln("Warning: <info>$sourceInput</info> is a file, but <info>$targetInput</info> is a folder"); + } + $wouldRequireDelete = true; + } else { + $targetInput = $targetNode->getFullPath($node->getName()); + $targetNode = $this->fileUtils->getNode($targetInput); + } + } else { + if ($node instanceof Folder) { + if (!$force) { + $output->writeln("Warning: <info>$sourceInput</info> is a folder, but <info>$targetInput</info> is a file"); + } + $wouldRequireDelete = true; + } + } + + if ($wouldRequireDelete && $targetNode->getInternalPath() === '') { + $output->writeln("<error>Mount root can't be overwritten with a different type</error>"); + return 1; + } + + if ($wouldRequireDelete && !$targetNode->isDeletable()) { + $output->writeln("<error>$targetInput can't be deleted to be replaced with $sourceInput</error>"); + return 1; + } + + if (!$force && $targetNode) { + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $question = new ConfirmationQuestion("<info>" . $targetInput . "</info> already exists, overwrite? [y/N] ", false); + if (!$helper->ask($input, $output, $question)) { + return 1; + } + } + } + + if ($wouldRequireDelete && $targetNode) { + $targetNode->delete(); + } + + $node->copy($targetInput); + + return 0; + } + +} diff --git a/apps/files/lib/Command/Move.php b/apps/files/lib/Command/Move.php new file mode 100644 index 00000000000..ac84dfa19b3 --- /dev/null +++ b/apps/files/lib/Command/Move.php @@ -0,0 +1,122 @@ +<?php + +declare(strict_types=1); +/** + * @copyright Copyright (c) 2023 Robin Appelman <robin@icewind.nl> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files\Command; + +use OC\Core\Command\Info\FileUtils; +use OCP\Files\Folder; +use OCP\Files\File; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +class Move extends Command { + private FileUtils $fileUtils; + + public function __construct(FileUtils $fileUtils) { + $this->fileUtils = $fileUtils; + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('files:move') + ->setDescription('Move a file or folder') + ->addArgument('source', InputArgument::REQUIRED, "Source file id or path") + ->addArgument('target', InputArgument::REQUIRED, "Target path") + ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for configuration and don't output any warnings"); + } + + public function execute(InputInterface $input, OutputInterface $output): int { + $sourceInput = $input->getArgument('source'); + $targetInput = $input->getArgument('target'); + $force = $input->getOption('force'); + + $node = $this->fileUtils->getNode($sourceInput); + $targetNode = $this->fileUtils->getNode($targetInput); + + if (!$node) { + $output->writeln("<error>file $sourceInput not found</error>"); + return 1; + } + + $targetParentPath = dirname(rtrim($targetInput, '/')); + $targetParent = $this->fileUtils->getNode($targetParentPath); + if (!$targetParent) { + $output->writeln("<error>Target parent path $targetParentPath doesn't exist</error>"); + return 1; + } + + $wouldRequireDelete = false; + + if ($targetNode) { + if (!$targetNode->isUpdateable()) { + $output->writeln("<error>$targetInput already exists and isn't writable</error>"); + return 1; + } + + if ($node instanceof Folder && $targetNode instanceof File) { + $output->writeln("Warning: <info>$sourceInput</info> is a folder, but <info>$targetInput</info> is a file"); + $wouldRequireDelete = true; + } + + if ($node instanceof File && $targetNode instanceof Folder) { + $output->writeln("Warning: <info>$sourceInput</info> is a file, but <info>$targetInput</info> is a folder"); + $wouldRequireDelete = true; + } + + if ($wouldRequireDelete && $targetNode->getInternalPath() === '') { + $output->writeln("<error>Mount root can't be overwritten with a different type</error>"); + return 1; + } + + if ($wouldRequireDelete && !$targetNode->isDeletable()) { + $output->writeln("<error>$targetInput can't be deleted to be replaced with $sourceInput</error>"); + return 1; + } + + if (!$force) { + /** @var QuestionHelper $helper */ + $helper = $this->getHelper('question'); + + $question = new ConfirmationQuestion("<info>" . $targetInput . "</info> already exists, overwrite? [y/N] ", false); + if (!$helper->ask($input, $output, $question)) { + return 1; + } + } + } + + if ($wouldRequireDelete && $targetNode) { + $targetNode->delete(); + } + + $node->move($targetInput); + + return 0; + } + +} diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index f8911c4d104..3d490f06b75 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -60,8 +60,6 @@ use OCP\Share\IManager; use OCP\Share\IShare; /** - * Class ApiController - * * @package OCA\Files\Controller */ class ApiController extends Controller { @@ -104,10 +102,14 @@ class ApiController extends Controller { * @NoCSRFRequired * @StrictCookieRequired * - * @param int $x - * @param int $y + * @param int $x Width of the thumbnail + * @param int $y Height of the thumbnail * @param string $file URL-encoded filename - * @return DataResponse|FileDisplayResponse + * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, array{message?: string}, array{}> + * + * 200: Thumbnail returned + * 400: Getting thumbnail is not possible + * 404: File not found */ public function getThumbnail($x, $y, $file) { if ($x < 1 || $y < 1) { @@ -386,6 +388,12 @@ class ApiController extends Controller { /** * @NoAdminRequired * @NoCSRFRequired + * + * Get the service-worker Javascript for previews + * + * @psalm-suppress MoreSpecificReturnType The value of Service-Worker-Allowed is not relevant + * @psalm-suppress LessSpecificReturnStatement The value of Service-Worker-Allowed is not relevant + * @return StreamResponse<Http::STATUS_OK, array{Content-Type: 'application/javascript', Service-Worker-Allowed: string}> */ public function serviceWorker(): StreamResponse { $response = new StreamResponse(__DIR__ . '/../../../../dist/preview-service-worker.js'); diff --git a/apps/files/lib/Controller/DirectEditingController.php b/apps/files/lib/Controller/DirectEditingController.php index 9b48d6958aa..d58be166e79 100644 --- a/apps/files/lib/Controller/DirectEditingController.php +++ b/apps/files/lib/Controller/DirectEditingController.php @@ -63,6 +63,9 @@ class DirectEditingController extends OCSController { /** * @NoAdminRequired + * + * Get the direct editing capabilities + * @return DataResponse<Http::STATUS_OK, array{editors: array<string, array{id: string, name: string, mimetypes: string[], optionalMimetypes: string[], secure: bool}>, creators: array<string, array{id: string, editor: string, name: string, extension: string, templates: bool, mimetypes: string[]}>}, array{}> */ public function info(): DataResponse { $response = new DataResponse($this->directEditingService->getDirectEditingCapabilitites()); @@ -72,6 +75,18 @@ class DirectEditingController extends OCSController { /** * @NoAdminRequired + * + * Create a file for direct editing + * + * @param string $path Path of the file + * @param string $editorId ID of the editor + * @param string $creatorId ID of the creator + * @param ?string $templateId ID of the template + * + * @return DataResponse<Http::STATUS_OK, array{url: string}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}> + * + * 200: URL for direct editing returned + * 403: Opening file is not allowed */ public function create(string $path, string $editorId, string $creatorId, string $templateId = null): DataResponse { if (!$this->directEditingManager->isEnabled()) { @@ -92,6 +107,17 @@ class DirectEditingController extends OCSController { /** * @NoAdminRequired + * + * Open a file for direct editing + * + * @param string $path Path of the file + * @param ?string $editorId ID of the editor + * @param ?int $fileId ID of the file + * + * @return DataResponse<Http::STATUS_OK, array{url: string}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}> + * + * 200: URL for direct editing returned + * 403: Opening file is not allowed */ public function open(string $path, string $editorId = null, ?int $fileId = null): DataResponse { if (!$this->directEditingManager->isEnabled()) { @@ -114,6 +140,15 @@ class DirectEditingController extends OCSController { /** * @NoAdminRequired + * + * Get the templates for direct editing + * + * @param string $editorId ID of the editor + * @param string $creatorId ID of the creator + * + * @return DataResponse<Http::STATUS_OK, array{templates: array<string, array{id: string, title: string, preview: ?string, extension: string, mimetype: string}>}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}> + * + * 200: Templates returned */ public function templates(string $editorId, string $creatorId): DataResponse { if (!$this->directEditingManager->isEnabled()) { diff --git a/apps/files/lib/Controller/DirectEditingViewController.php b/apps/files/lib/Controller/DirectEditingViewController.php index 30d54d5ceb3..0741b58cfe9 100644 --- a/apps/files/lib/Controller/DirectEditingViewController.php +++ b/apps/files/lib/Controller/DirectEditingViewController.php @@ -24,6 +24,7 @@ namespace OCA\Files\Controller; use Exception; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Http\Response; use OCP\DirectEditing\IManager; @@ -32,6 +33,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\ILogger; use OCP\IRequest; +#[IgnoreOpenAPI] class DirectEditingViewController extends Controller { /** @var IEventDispatcher */ diff --git a/apps/files/lib/Controller/OpenLocalEditorController.php b/apps/files/lib/Controller/OpenLocalEditorController.php index 7d784196361..d9fb80f2d2b 100644 --- a/apps/files/lib/Controller/OpenLocalEditorController.php +++ b/apps/files/lib/Controller/OpenLocalEditorController.php @@ -70,6 +70,14 @@ class OpenLocalEditorController extends OCSController { /** * @NoAdminRequired * @UserRateThrottle(limit=10, period=120) + * + * Create a local editor + * + * @param string $path Path of the file + * + * @return DataResponse<Http::STATUS_OK, array{userId: ?string, pathHash: string, expirationTime: int, token: string}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array<empty>, array{}> + * + * 200: Local editor returned */ public function create(string $path): DataResponse { $pathHash = sha1($path); @@ -107,6 +115,16 @@ class OpenLocalEditorController extends OCSController { /** * @NoAdminRequired * @BruteForceProtection(action=openLocalEditor) + * + * Validate a local editor + * + * @param string $path Path of the file + * @param string $token Token of the local editor + * + * @return DataResponse<Http::STATUS_OK, array{userId: string, pathHash: string, expirationTime: int, token: string}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array<empty>, array{}> + * + * 200: Local editor validated successfully + * 404: Local editor not found */ public function validate(string $path, string $token): DataResponse { $pathHash = sha1($path); diff --git a/apps/files/lib/Controller/TemplateController.php b/apps/files/lib/Controller/TemplateController.php index d04d86760e6..645350010ec 100644 --- a/apps/files/lib/Controller/TemplateController.php +++ b/apps/files/lib/Controller/TemplateController.php @@ -26,13 +26,21 @@ declare(strict_types=1); */ namespace OCA\Files\Controller; +use OCA\Files\ResponseDefinitions; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSForbiddenException; use OCP\AppFramework\OCSController; use OCP\Files\GenericFileException; use OCP\Files\Template\ITemplateManager; +use OCP\Files\Template\TemplateFileCreator; use OCP\IRequest; +/** + * @psalm-import-type FilesTemplate from ResponseDefinitions + * @psalm-import-type FilesTemplateFile from ResponseDefinitions + * @psalm-import-type FilesTemplateFileCreator from ResponseDefinitions + */ class TemplateController extends OCSController { protected $templateManager; @@ -43,6 +51,10 @@ class TemplateController extends OCSController { /** * @NoAdminRequired + * + * List the available templates + * + * @return DataResponse<Http::STATUS_OK, array<FilesTemplateFileCreator>, array{}> */ public function list(): DataResponse { return new DataResponse($this->templateManager->listTemplates()); @@ -50,7 +62,17 @@ class TemplateController extends OCSController { /** * @NoAdminRequired - * @throws OCSForbiddenException + * + * Create a template + * + * @param string $filePath Path of the file + * @param string $templatePath Name of the template + * @param string $templateType Type of the template + * + * @return DataResponse<Http::STATUS_OK, FilesTemplateFile, array{}> + * @throws OCSForbiddenException Creating template is not allowed + * + * 200: Template created successfully */ public function create(string $filePath, string $templatePath = '', string $templateType = 'user'): DataResponse { try { @@ -62,13 +84,24 @@ class TemplateController extends OCSController { /** * @NoAdminRequired + * + * Initialize the template directory + * + * @param string $templatePath Path of the template directory + * @param bool $copySystemTemplates Whether to copy the system templates to the template directory + * + * @return DataResponse<Http::STATUS_OK, array{template_path: string, templates: FilesTemplateFileCreator[]}, array{}> + * @throws OCSForbiddenException Initializing the template directory is not allowed + * + * 200: Template directory initialized successfully */ public function path(string $templatePath = '', bool $copySystemTemplates = false) { try { + /** @var string $templatePath */ $templatePath = $this->templateManager->initializeTemplateDirectory($templatePath, null, $copySystemTemplates); return new DataResponse([ 'template_path' => $templatePath, - 'templates' => $this->templateManager->listCreators() + 'templates' => array_map(fn(TemplateFileCreator $creator) => $creator->jsonSerialize(), $this->templateManager->listCreators()), ]); } catch (\Exception $e) { throw new OCSForbiddenException($e->getMessage()); diff --git a/apps/files/lib/Controller/TransferOwnershipController.php b/apps/files/lib/Controller/TransferOwnershipController.php index 5abd65444bf..ce68b28349e 100644 --- a/apps/files/lib/Controller/TransferOwnershipController.php +++ b/apps/files/lib/Controller/TransferOwnershipController.php @@ -82,6 +82,17 @@ class TransferOwnershipController extends OCSController { /** * @NoAdminRequired + * + * Transfer the ownership to another user + * + * @param string $recipient Username of the recipient + * @param string $path Path of the file + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN, array<empty>, array{}> + * + * 200: Ownership transferred successfully + * 400: Transferring ownership is not possible + * 403: Transferring ownership is not allowed */ public function transfer(string $recipient, string $path): DataResponse { $recipientUser = $this->userManager->get($recipient); @@ -127,6 +138,16 @@ class TransferOwnershipController extends OCSController { /** * @NoAdminRequired + * + * Accept an ownership transfer + * + * @param int $id ID of the ownership transfer + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array<empty>, array{}> + * + * 200: Ownership transfer accepted successfully + * 403: Accepting ownership transfer is not allowed + * 404: Ownership transfer not found */ public function accept(int $id): DataResponse { try { @@ -160,6 +181,16 @@ class TransferOwnershipController extends OCSController { /** * @NoAdminRequired + * + * Reject an ownership transfer + * + * @param int $id ID of the ownership transfer + * + * @return DataResponse<Http::STATUS_OK|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array<empty>, array{}> + * + * 200: Ownership transfer rejected successfully + * 403: Rejecting ownership transfer is not allowed + * 404: Ownership transfer not found */ public function reject(int $id): DataResponse { try { diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php index 43be43aa116..01f85a7c939 100644 --- a/apps/files/lib/Controller/ViewController.php +++ b/apps/files/lib/Controller/ViewController.php @@ -35,6 +35,7 @@ */ namespace OCA\Files\Controller; +use OC\AppFramework\Http; use OCA\Files\Activity\Helper; use OCA\Files\AppInfo\Application; use OCA\Files\Event\LoadAdditionalScriptsEvent; @@ -44,6 +45,7 @@ use OCA\Files\Service\ViewConfig; use OCA\Viewer\Event\LoadViewer; use OCP\App\IAppManager; use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\Response; @@ -63,10 +65,9 @@ use OCP\IUserSession; use OCP\Share\IManager; /** - * Class ViewController - * * @package OCA\Files\Controller */ +#[IgnoreOpenAPI] class ViewController extends Controller { private IURLGenerator $urlGenerator; private IL10N $l10n; diff --git a/apps/files/lib/DirectEditingCapabilities.php b/apps/files/lib/DirectEditingCapabilities.php index 10c8e95105a..1bc00519ae8 100644 --- a/apps/files/lib/DirectEditingCapabilities.php +++ b/apps/files/lib/DirectEditingCapabilities.php @@ -38,6 +38,9 @@ class DirectEditingCapabilities implements ICapability, IInitialStateExcludedCap $this->urlGenerator = $urlGenerator; } + /** + * @return array{files: array{directEditing: array{url: string, etag: string, supportsFileId: bool}}} + */ public function getCapabilities() { return [ 'files' => [ diff --git a/apps/files/lib/ResponseDefinitions.php b/apps/files/lib/ResponseDefinitions.php new file mode 100644 index 00000000000..8a27ec4bb2f --- /dev/null +++ b/apps/files/lib/ResponseDefinitions.php @@ -0,0 +1,67 @@ +<?php +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2023 Kate Döen <kate.doeen@nextcloud.com> + * + * @author Kate Döen <kate.doeen@nextcloud.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files; + +/** + * @psalm-type FilesTemplate = array{ + * templateType: string, + * templateId: string, + * basename: string, + * etag: string, + * fileid: int, + * filename: string, + * lastmod: int, + * mime: string, + * size: int, + * type: string, + * hasPreview: bool, + * previewUrl: ?string, + * } + * + * @psalm-type FilesTemplateFile = array{ + * basename: string, + * etag: string, + * fileid: int, + * filename: ?string, + * lastmod: int, + * mime: string, + * size: int, + * type: string, + * hasPreview: bool, + * } + * + * @psalm-type FilesTemplateFileCreator = array{ + * app: string, + * label: string, + * extension: string, + * iconClass: ?string, + * mimetypes: string[], + * ratio: ?float, + * actionLabel: string, + * } + */ +class ResponseDefinitions { +} |