@@ -34,53 +34,53 @@ |
||
| 34 | 34 | use Symfony\Component\Console\Output\OutputInterface; |
| 35 | 35 | |
| 36 | 36 | class Put extends Command { |
| 37 | - private FileUtils $fileUtils; |
|
| 38 | - private IRootFolder $rootFolder; |
|
| 37 | + private FileUtils $fileUtils; |
|
| 38 | + private IRootFolder $rootFolder; |
|
| 39 | 39 | |
| 40 | - public function __construct(FileUtils $fileUtils, IRootFolder $rootFolder) { |
|
| 41 | - $this->fileUtils = $fileUtils; |
|
| 42 | - $this->rootFolder = $rootFolder; |
|
| 43 | - parent::__construct(); |
|
| 44 | - } |
|
| 40 | + public function __construct(FileUtils $fileUtils, IRootFolder $rootFolder) { |
|
| 41 | + $this->fileUtils = $fileUtils; |
|
| 42 | + $this->rootFolder = $rootFolder; |
|
| 43 | + parent::__construct(); |
|
| 44 | + } |
|
| 45 | 45 | |
| 46 | - protected function configure(): void { |
|
| 47 | - $this |
|
| 48 | - ->setName('files:put') |
|
| 49 | - ->setDescription('Write contents of a file') |
|
| 50 | - ->addArgument('input', InputArgument::REQUIRED, "Source local path, use - to read from STDIN") |
|
| 51 | - ->addArgument('file', InputArgument::REQUIRED, "Target Nextcloud file path to write to or fileid of existing file"); |
|
| 52 | - } |
|
| 46 | + protected function configure(): void { |
|
| 47 | + $this |
|
| 48 | + ->setName('files:put') |
|
| 49 | + ->setDescription('Write contents of a file') |
|
| 50 | + ->addArgument('input', InputArgument::REQUIRED, "Source local path, use - to read from STDIN") |
|
| 51 | + ->addArgument('file', InputArgument::REQUIRED, "Target Nextcloud file path to write to or fileid of existing file"); |
|
| 52 | + } |
|
| 53 | 53 | |
| 54 | - public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 55 | - $fileOutput = $input->getArgument('file'); |
|
| 56 | - $inputName = $input->getArgument('input'); |
|
| 57 | - $node = $this->fileUtils->getNode($fileOutput); |
|
| 54 | + public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 55 | + $fileOutput = $input->getArgument('file'); |
|
| 56 | + $inputName = $input->getArgument('input'); |
|
| 57 | + $node = $this->fileUtils->getNode($fileOutput); |
|
| 58 | 58 | |
| 59 | - if ($node instanceof Folder) { |
|
| 60 | - $output->writeln("<error>$fileOutput is a folder</error>"); |
|
| 61 | - return 1; |
|
| 62 | - } |
|
| 63 | - if (!$node and is_numeric($fileOutput)) { |
|
| 64 | - $output->writeln("<error>$fileOutput not found</error>"); |
|
| 65 | - return 1; |
|
| 66 | - } |
|
| 59 | + if ($node instanceof Folder) { |
|
| 60 | + $output->writeln("<error>$fileOutput is a folder</error>"); |
|
| 61 | + return 1; |
|
| 62 | + } |
|
| 63 | + if (!$node and is_numeric($fileOutput)) { |
|
| 64 | + $output->writeln("<error>$fileOutput not found</error>"); |
|
| 65 | + return 1; |
|
| 66 | + } |
|
| 67 | 67 | |
| 68 | - $source = ($inputName === null || $inputName === '-') ? STDIN : fopen($inputName, 'r'); |
|
| 69 | - if (!$source) { |
|
| 70 | - $output->writeln("<error>Failed to open $inputName</error>"); |
|
| 71 | - return 1; |
|
| 72 | - } |
|
| 73 | - if ($node instanceof File) { |
|
| 74 | - $target = $node->fopen('w'); |
|
| 75 | - if (!$target) { |
|
| 76 | - $output->writeln("<error>Failed to open $fileOutput</error>"); |
|
| 77 | - return 1; |
|
| 78 | - } |
|
| 79 | - stream_copy_to_stream($source, $target); |
|
| 80 | - } else { |
|
| 81 | - $this->rootFolder->newFile($fileOutput, $source); |
|
| 82 | - } |
|
| 83 | - return 0; |
|
| 84 | - } |
|
| 68 | + $source = ($inputName === null || $inputName === '-') ? STDIN : fopen($inputName, 'r'); |
|
| 69 | + if (!$source) { |
|
| 70 | + $output->writeln("<error>Failed to open $inputName</error>"); |
|
| 71 | + return 1; |
|
| 72 | + } |
|
| 73 | + if ($node instanceof File) { |
|
| 74 | + $target = $node->fopen('w'); |
|
| 75 | + if (!$target) { |
|
| 76 | + $output->writeln("<error>Failed to open $fileOutput</error>"); |
|
| 77 | + return 1; |
|
| 78 | + } |
|
| 79 | + stream_copy_to_stream($source, $target); |
|
| 80 | + } else { |
|
| 81 | + $this->rootFolder->newFile($fileOutput, $source); |
|
| 82 | + } |
|
| 83 | + return 0; |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | 86 | } |
@@ -32,58 +32,58 @@ |
||
| 32 | 32 | use Symfony\Component\Console\Output\OutputInterface; |
| 33 | 33 | |
| 34 | 34 | class Get extends Command { |
| 35 | - private FileUtils $fileUtils; |
|
| 35 | + private FileUtils $fileUtils; |
|
| 36 | 36 | |
| 37 | - public function __construct(FileUtils $fileUtils) { |
|
| 38 | - $this->fileUtils = $fileUtils; |
|
| 39 | - parent::__construct(); |
|
| 40 | - } |
|
| 37 | + public function __construct(FileUtils $fileUtils) { |
|
| 38 | + $this->fileUtils = $fileUtils; |
|
| 39 | + parent::__construct(); |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - protected function configure(): void { |
|
| 43 | - $this |
|
| 44 | - ->setName('files:get') |
|
| 45 | - ->setDescription('Get the contents of a file') |
|
| 46 | - ->addArgument('file', InputArgument::REQUIRED, "Source file id or Nextcloud path") |
|
| 47 | - ->addArgument('output', InputArgument::OPTIONAL, "Target local file to output to, defaults to STDOUT"); |
|
| 48 | - } |
|
| 42 | + protected function configure(): void { |
|
| 43 | + $this |
|
| 44 | + ->setName('files:get') |
|
| 45 | + ->setDescription('Get the contents of a file') |
|
| 46 | + ->addArgument('file', InputArgument::REQUIRED, "Source file id or Nextcloud path") |
|
| 47 | + ->addArgument('output', InputArgument::OPTIONAL, "Target local file to output to, defaults to STDOUT"); |
|
| 48 | + } |
|
| 49 | 49 | |
| 50 | - public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 51 | - $fileInput = $input->getArgument('file'); |
|
| 52 | - $outputName = $input->getArgument('output'); |
|
| 53 | - $node = $this->fileUtils->getNode($fileInput); |
|
| 50 | + public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 51 | + $fileInput = $input->getArgument('file'); |
|
| 52 | + $outputName = $input->getArgument('output'); |
|
| 53 | + $node = $this->fileUtils->getNode($fileInput); |
|
| 54 | 54 | |
| 55 | - if (!$node) { |
|
| 56 | - $output->writeln("<error>file $fileInput not found</error>"); |
|
| 57 | - return 1; |
|
| 58 | - } |
|
| 55 | + if (!$node) { |
|
| 56 | + $output->writeln("<error>file $fileInput not found</error>"); |
|
| 57 | + return 1; |
|
| 58 | + } |
|
| 59 | 59 | |
| 60 | - if ($node instanceof File) { |
|
| 61 | - $isTTY = stream_isatty(STDOUT); |
|
| 62 | - if ($outputName === null && $isTTY && $node->getMimePart() !== 'text') { |
|
| 63 | - $output->writeln([ |
|
| 64 | - "<error>Warning: Binary output can mess up your terminal</error>", |
|
| 65 | - " Use <info>occ files:get $fileInput -</info> to output it to the terminal anyway", |
|
| 66 | - " Or <info>occ files:get $fileInput <FILE></info> to save to a file instead" |
|
| 67 | - ]); |
|
| 68 | - return 1; |
|
| 69 | - } |
|
| 70 | - $source = $node->fopen('r'); |
|
| 71 | - if (!$source) { |
|
| 72 | - $output->writeln("<error>Failed to open $fileInput for reading</error>"); |
|
| 73 | - return 1; |
|
| 74 | - } |
|
| 75 | - $target = ($outputName === null || $outputName === '-') ? STDOUT : fopen($outputName, 'w'); |
|
| 76 | - if (!$target) { |
|
| 77 | - $output->writeln("<error>Failed to open $outputName for reading</error>"); |
|
| 78 | - return 1; |
|
| 79 | - } |
|
| 60 | + if ($node instanceof File) { |
|
| 61 | + $isTTY = stream_isatty(STDOUT); |
|
| 62 | + if ($outputName === null && $isTTY && $node->getMimePart() !== 'text') { |
|
| 63 | + $output->writeln([ |
|
| 64 | + "<error>Warning: Binary output can mess up your terminal</error>", |
|
| 65 | + " Use <info>occ files:get $fileInput -</info> to output it to the terminal anyway", |
|
| 66 | + " Or <info>occ files:get $fileInput <FILE></info> to save to a file instead" |
|
| 67 | + ]); |
|
| 68 | + return 1; |
|
| 69 | + } |
|
| 70 | + $source = $node->fopen('r'); |
|
| 71 | + if (!$source) { |
|
| 72 | + $output->writeln("<error>Failed to open $fileInput for reading</error>"); |
|
| 73 | + return 1; |
|
| 74 | + } |
|
| 75 | + $target = ($outputName === null || $outputName === '-') ? STDOUT : fopen($outputName, 'w'); |
|
| 76 | + if (!$target) { |
|
| 77 | + $output->writeln("<error>Failed to open $outputName for reading</error>"); |
|
| 78 | + return 1; |
|
| 79 | + } |
|
| 80 | 80 | |
| 81 | - stream_copy_to_stream($source, $target); |
|
| 82 | - return 0; |
|
| 83 | - } else { |
|
| 84 | - $output->writeln("<error>$fileInput is a directory</error>"); |
|
| 85 | - return 1; |
|
| 86 | - } |
|
| 87 | - } |
|
| 81 | + stream_copy_to_stream($source, $target); |
|
| 82 | + return 0; |
|
| 83 | + } else { |
|
| 84 | + $output->writeln("<error>$fileInput is a directory</error>"); |
|
| 85 | + return 1; |
|
| 86 | + } |
|
| 87 | + } |
|
| 88 | 88 | |
| 89 | 89 | } |
@@ -35,82 +35,82 @@ |
||
| 35 | 35 | use Symfony\Component\Console\Question\ConfirmationQuestion; |
| 36 | 36 | |
| 37 | 37 | class Delete extends Command { |
| 38 | - private FileUtils $fileUtils; |
|
| 38 | + private FileUtils $fileUtils; |
|
| 39 | 39 | |
| 40 | - public function __construct(FileUtils $fileUtils) { |
|
| 41 | - $this->fileUtils = $fileUtils; |
|
| 42 | - parent::__construct(); |
|
| 43 | - } |
|
| 40 | + public function __construct(FileUtils $fileUtils) { |
|
| 41 | + $this->fileUtils = $fileUtils; |
|
| 42 | + parent::__construct(); |
|
| 43 | + } |
|
| 44 | 44 | |
| 45 | - protected function configure(): void { |
|
| 46 | - $this |
|
| 47 | - ->setName('files:delete') |
|
| 48 | - ->setDescription('Delete a file or folder') |
|
| 49 | - ->addArgument('file', InputArgument::REQUIRED, "File id or path") |
|
| 50 | - ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for configuration and don't output any warnings"); |
|
| 51 | - } |
|
| 45 | + protected function configure(): void { |
|
| 46 | + $this |
|
| 47 | + ->setName('files:delete') |
|
| 48 | + ->setDescription('Delete a file or folder') |
|
| 49 | + ->addArgument('file', InputArgument::REQUIRED, "File id or path") |
|
| 50 | + ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for configuration and don't output any warnings"); |
|
| 51 | + } |
|
| 52 | 52 | |
| 53 | - public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 54 | - $fileInput = $input->getArgument('file'); |
|
| 55 | - $inputIsId = is_numeric($fileInput); |
|
| 56 | - $force = $input->getOption('force'); |
|
| 57 | - $node = $this->fileUtils->getNode($fileInput); |
|
| 53 | + public function execute(InputInterface $input, OutputInterface $output): int { |
|
| 54 | + $fileInput = $input->getArgument('file'); |
|
| 55 | + $inputIsId = is_numeric($fileInput); |
|
| 56 | + $force = $input->getOption('force'); |
|
| 57 | + $node = $this->fileUtils->getNode($fileInput); |
|
| 58 | 58 | |
| 59 | - if (!$node) { |
|
| 60 | - $output->writeln("<error>file $fileInput not found</error>"); |
|
| 61 | - return 1; |
|
| 62 | - } |
|
| 59 | + if (!$node) { |
|
| 60 | + $output->writeln("<error>file $fileInput not found</error>"); |
|
| 61 | + return 1; |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - $deleteConfirmed = $force; |
|
| 65 | - if (!$deleteConfirmed) { |
|
| 66 | - /** @var QuestionHelper $helper */ |
|
| 67 | - $helper = $this->getHelper('question'); |
|
| 68 | - $storage = $node->getStorage(); |
|
| 69 | - if (!$inputIsId && $storage->instanceOfStorage(SharedStorage::class) && $node->getInternalPath() === '') { |
|
| 70 | - /** @var SharedStorage $storage */ |
|
| 71 | - [,$user] = explode('/', $fileInput, 3); |
|
| 72 | - $question = new ConfirmationQuestion("<info>$fileInput</info> in a shared file, do you want to unshare the file from <info>$user</info> instead of deleting the source file? [Y/n] ", true); |
|
| 73 | - if ($helper->ask($input, $output, $question)) { |
|
| 74 | - $storage->unshareStorage(); |
|
| 75 | - return 0; |
|
| 76 | - } else { |
|
| 77 | - $node = $storage->getShare()->getNode(); |
|
| 78 | - $output->writeln(""); |
|
| 79 | - } |
|
| 80 | - } |
|
| 64 | + $deleteConfirmed = $force; |
|
| 65 | + if (!$deleteConfirmed) { |
|
| 66 | + /** @var QuestionHelper $helper */ |
|
| 67 | + $helper = $this->getHelper('question'); |
|
| 68 | + $storage = $node->getStorage(); |
|
| 69 | + if (!$inputIsId && $storage->instanceOfStorage(SharedStorage::class) && $node->getInternalPath() === '') { |
|
| 70 | + /** @var SharedStorage $storage */ |
|
| 71 | + [,$user] = explode('/', $fileInput, 3); |
|
| 72 | + $question = new ConfirmationQuestion("<info>$fileInput</info> in a shared file, do you want to unshare the file from <info>$user</info> instead of deleting the source file? [Y/n] ", true); |
|
| 73 | + if ($helper->ask($input, $output, $question)) { |
|
| 74 | + $storage->unshareStorage(); |
|
| 75 | + return 0; |
|
| 76 | + } else { |
|
| 77 | + $node = $storage->getShare()->getNode(); |
|
| 78 | + $output->writeln(""); |
|
| 79 | + } |
|
| 80 | + } |
|
| 81 | 81 | |
| 82 | - $filesByUsers = $this->fileUtils->getFilesByUser($node); |
|
| 83 | - if (count($filesByUsers) > 1) { |
|
| 84 | - $output->writeln("Warning: the provided file is accessible by more than one user"); |
|
| 85 | - $output->writeln(" all of the following users will lose access to the file when deleted:"); |
|
| 86 | - $output->writeln(""); |
|
| 87 | - foreach ($filesByUsers as $user => $filesByUser) { |
|
| 88 | - $output->writeln($user . ":"); |
|
| 89 | - foreach($filesByUser as $file) { |
|
| 90 | - $output->writeln(" - " . $file->getPath()); |
|
| 91 | - } |
|
| 92 | - } |
|
| 93 | - $output->writeln(""); |
|
| 94 | - } |
|
| 82 | + $filesByUsers = $this->fileUtils->getFilesByUser($node); |
|
| 83 | + if (count($filesByUsers) > 1) { |
|
| 84 | + $output->writeln("Warning: the provided file is accessible by more than one user"); |
|
| 85 | + $output->writeln(" all of the following users will lose access to the file when deleted:"); |
|
| 86 | + $output->writeln(""); |
|
| 87 | + foreach ($filesByUsers as $user => $filesByUser) { |
|
| 88 | + $output->writeln($user . ":"); |
|
| 89 | + foreach($filesByUser as $file) { |
|
| 90 | + $output->writeln(" - " . $file->getPath()); |
|
| 91 | + } |
|
| 92 | + } |
|
| 93 | + $output->writeln(""); |
|
| 94 | + } |
|
| 95 | 95 | |
| 96 | - if ($node instanceof Folder) { |
|
| 97 | - $maybeContents = " and all it's contents"; |
|
| 98 | - } else { |
|
| 99 | - $maybeContents = ""; |
|
| 100 | - } |
|
| 101 | - $question = new ConfirmationQuestion("Delete " . $node->getPath() . $maybeContents . "? [y/N] ", false); |
|
| 102 | - $deleteConfirmed = $helper->ask($input, $output, $question); |
|
| 103 | - } |
|
| 96 | + if ($node instanceof Folder) { |
|
| 97 | + $maybeContents = " and all it's contents"; |
|
| 98 | + } else { |
|
| 99 | + $maybeContents = ""; |
|
| 100 | + } |
|
| 101 | + $question = new ConfirmationQuestion("Delete " . $node->getPath() . $maybeContents . "? [y/N] ", false); |
|
| 102 | + $deleteConfirmed = $helper->ask($input, $output, $question); |
|
| 103 | + } |
|
| 104 | 104 | |
| 105 | - if ($deleteConfirmed) { |
|
| 106 | - if ($node->isDeletable()) { |
|
| 107 | - $node->delete(); |
|
| 108 | - } else { |
|
| 109 | - $output->writeln("<error>File cannot be deleted, insufficient permissions.</error>"); |
|
| 110 | - } |
|
| 111 | - } |
|
| 105 | + if ($deleteConfirmed) { |
|
| 106 | + if ($node->isDeletable()) { |
|
| 107 | + $node->delete(); |
|
| 108 | + } else { |
|
| 109 | + $output->writeln("<error>File cannot be deleted, insufficient permissions.</error>"); |
|
| 110 | + } |
|
| 111 | + } |
|
| 112 | 112 | |
| 113 | - return 0; |
|
| 114 | - } |
|
| 113 | + return 0; |
|
| 114 | + } |
|
| 115 | 115 | |
| 116 | 116 | } |