Skip to content

Commit cd74d3c

Browse files
committed
refactor: Use the new AsCommand attribute to port two files commands
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
1 parent 812f159 commit cd74d3c

2 files changed

Lines changed: 65 additions & 77 deletions

File tree

‎apps/files/lib/Command/Move.php‎

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,89 +9,83 @@
99
namespace OCA\Files\Command;
1010

1111
use OC\Core\Command\Info\FileUtils;
12+
use OCP\Console\Attribute\Argument;
13+
use OCP\Console\Attribute\AsCommand;
14+
use OCP\Console\Attribute\Option;
15+
use OCP\Console\ExitCode;
16+
use OCP\Console\IOutput;
17+
use OCP\Console\IQuestionHelper;
1218
use OCP\Files\File;
1319
use OCP\Files\Folder;
14-
use Symfony\Component\Console\Command\Command;
15-
use Symfony\Component\Console\Helper\QuestionHelper;
16-
use Symfony\Component\Console\Input\InputArgument;
17-
use Symfony\Component\Console\Input\InputInterface;
18-
use Symfony\Component\Console\Input\InputOption;
19-
use Symfony\Component\Console\Output\OutputInterface;
2020
use Symfony\Component\Console\Question\ConfirmationQuestion;
2121

22-
class Move extends Command {
22+
#[AsCommand(
23+
name: 'files:move',
24+
description: 'Move a file or a folder',
25+
)]
26+
class Move {
2327
public function __construct(
24-
private FileUtils $fileUtils,
28+
private readonly FileUtils $fileUtils,
2529
) {
26-
parent::__construct();
2730
}
2831

29-
#[\Override]
30-
protected function configure(): void {
31-
$this
32-
->setName('files:move')
33-
->setDescription('Move a file or folder')
34-
->addArgument('source', InputArgument::REQUIRED, 'Source file id or path')
35-
->addArgument('target', InputArgument::REQUIRED, 'Target path')
36-
->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for configuration and don't output any warnings");
37-
}
38-
39-
#[\Override]
40-
public function execute(InputInterface $input, OutputInterface $output): int {
41-
$sourceInput = $input->getArgument('source');
42-
$targetInput = $input->getArgument('target');
43-
$force = $input->getOption('force');
44-
45-
$node = $this->fileUtils->getNode($sourceInput);
46-
$targetNode = $this->fileUtils->getNode($targetInput);
32+
public function __invoke(
33+
IOutput $output,
34+
IQuestionHelper $questionHelper,
35+
#[Argument(description: 'Source file id or path')] string $source,
36+
#[Argument(description: 'Target path')] string $target,
37+
#[Option(
38+
description: "Don't ask for configuration and don't output any warnings",
39+
shortcut: 'f',
40+
)] bool $force = false,
41+
): ExitCode {
42+
$node = $this->fileUtils->getNode($source);
43+
$targetNode = $this->fileUtils->getNode($target);
4744

4845
if (!$node) {
49-
$output->writeln("<error>file $sourceInput not found</error>");
50-
return 1;
46+
$output->writeln("<error>file $source not found</error>");
47+
return ExitCode::Failure;
5148
}
5249

53-
$targetParentPath = dirname(rtrim($targetInput, '/'));
50+
$targetParentPath = dirname(rtrim($target, '/'));
5451
$targetParent = $this->fileUtils->getNode($targetParentPath);
5552
if (!$targetParent) {
5653
$output->writeln("<error>Target parent path $targetParentPath doesn't exist</error>");
57-
return 1;
54+
return ExitCode::Failure;
5855
}
5956

6057
$wouldRequireDelete = false;
6158

6259
if ($targetNode) {
6360
if (!$targetNode->isUpdateable()) {
64-
$output->writeln("<error>$targetInput already exists and isn't writable</error>");
65-
return 1;
61+
$output->writeln("<error>$target already exists and isn't writable</error>");
62+
return ExitCode::Failure;
6663
}
6764

6865
if ($node instanceof Folder && $targetNode instanceof File) {
69-
$output->writeln("Warning: <info>$sourceInput</info> is a folder, but <info>$targetInput</info> is a file");
66+
$output->writeln("Warning: <info>$source</info> is a folder, but <info>$target</info> is a file");
7067
$wouldRequireDelete = true;
7168
}
7269

7370
if ($node instanceof File && $targetNode instanceof Folder) {
74-
$output->writeln("Warning: <info>$sourceInput</info> is a file, but <info>$targetInput</info> is a folder");
71+
$output->writeln("Warning: <info>$source</info> is a file, but <info>$target</info> is a folder");
7572
$wouldRequireDelete = true;
7673
}
7774

7875
if ($wouldRequireDelete && $targetNode->getInternalPath() === '') {
7976
$output->writeln("<error>Mount root can't be overwritten with a different type</error>");
80-
return 1;
77+
return ExitCode::Failure;
8178
}
8279

8380
if ($wouldRequireDelete && !$targetNode->isDeletable()) {
84-
$output->writeln("<error>$targetInput can't be deleted to be replaced with $sourceInput</error>");
85-
return 1;
81+
$output->writeln("<error>$target can't be deleted to be replaced with $source</error>");
82+
return ExitCode::Failure;
8683
}
8784

8885
if (!$force) {
89-
/** @var QuestionHelper $helper */
90-
$helper = $this->getHelper('question');
91-
92-
$question = new ConfirmationQuestion('<info>' . $targetInput . '</info> already exists, overwrite? [y/N] ', false);
93-
if (!$helper->ask($input, $output, $question)) {
94-
return 1;
86+
$question = new ConfirmationQuestion('<info>' . $target . '</info> already exists, overwrite? [y/N] ', false);
87+
if (!$questionHelper->ask($question)) {
88+
return ExitCode::Failure;
9589
}
9690
}
9791
}
@@ -100,9 +94,8 @@ public function execute(InputInterface $input, OutputInterface $output): int {
10094
$targetNode->delete();
10195
}
10296

103-
$node->move($targetInput);
97+
$node->move($target);
10498

105-
return 0;
99+
return ExitCode::Success;
106100
}
107-
108101
}

‎apps/files/lib/Command/Touch.php‎

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,43 @@
1010

1111
use DateTimeImmutable;
1212
use OC\Core\Command\Info\FileUtils;
13+
use OCP\Console\Attribute\Argument;
14+
use OCP\Console\Attribute\AsCommand;
15+
use OCP\Console\Attribute\Option;
16+
use OCP\Console\ExitCode;
17+
use OCP\Console\IOutput;
1318
use OCP\Files\IRootFolder;
1419
use Psr\Clock\ClockInterface;
15-
use Symfony\Component\Console\Command\Command;
16-
use Symfony\Component\Console\Input\InputArgument;
17-
use Symfony\Component\Console\Input\InputInterface;
18-
use Symfony\Component\Console\Input\InputOption;
19-
use Symfony\Component\Console\Output\OutputInterface;
2020

21-
class Touch extends Command {
21+
#[AsCommand(
22+
name: 'files:touch',
23+
description: 'Update the last modified date of a file or folder, or create an empty file',
24+
)]
25+
class Touch {
2226
public function __construct(
2327
private readonly FileUtils $fileUtils,
2428
private readonly IRootFolder $rootFolder,
2529
private readonly ClockInterface $clock,
2630
) {
27-
parent::__construct();
2831
}
2932

30-
#[\Override]
31-
protected function configure(): void {
32-
$this
33-
->setName('files:touch')
34-
->setDescription('Update the last modified date of a file or folder, or create an empty file')
35-
->addArgument('file', InputArgument::REQUIRED, 'Nextcloud path or fileid for the file or folder to change the modified date of')
36-
->addOption('date', 'd', InputOption::VALUE_REQUIRED, 'Time to use as modified date instead of the current time. Acceptable formats are: ISO8601, "YYYY-MM-DD" and Unix time in seconds.')
37-
->addOption('no-create', 'c', InputOption::VALUE_NONE, 'Don\'t create an empty file if the target path doesn\'t exist');
38-
}
39-
40-
#[\Override]
41-
public function execute(InputInterface $input, OutputInterface $output): int {
42-
$fileInput = $input->getArgument('file');
43-
$node = $this->fileUtils->getNode($fileInput);
44-
$date = $input->getOption('date');
45-
$noCreate = $input->getOption('no-create');
33+
public function __invoke(
34+
IOutput $output,
35+
#[Argument(description: 'Nextcloud path or fileid for the file or folder to change the modified date of')]
36+
string $file,
37+
#[Option(name: 'no-create', description: 'Don\'t create an empty file if the target path doesn\'t exist', shortcut: 'c')]
38+
bool $noCreate = false,
39+
#[Option(description: 'Time to use as modified date instead of the current time. Acceptable formats are: ISO8601, "YYYY-MM-DD" and Unix time in seconds.', shortcut: 'd')]
40+
?string $date = null,
41+
): ExitCode {
42+
$node = $this->fileUtils->getNode($file);
4643

4744
if (!$node) {
48-
if ($noCreate || is_numeric($fileInput)) {
49-
$output->writeln("<error>$fileInput doesn't exist</error>");
50-
return self::FAILURE;
45+
if ($noCreate || is_numeric($file)) {
46+
$output->writeln("<error>$file doesn't exist</error>");
47+
return ExitCode::Failure;
5148
}
52-
$node = $this->rootFolder->newFile($fileInput);
49+
$node = $this->rootFolder->newFile($file);
5350
}
5451

5552
if ($date) {
@@ -62,15 +59,13 @@ public function execute(InputInterface $input, OutputInterface $output): int {
6259
}
6360
$node->touch($mtime->getTimestamp());
6461

65-
return self::SUCCESS;
62+
return ExitCode::Success;
6663
}
6764

6865
/**
6966
* @return \DateTimeImmutable|false
7067
*/
7168
protected function parseDateOption(string $input) {
72-
$date = false;
73-
7469
// Handle Unix timestamp
7570
if (filter_var($input, FILTER_VALIDATE_INT)) {
7671
return new DateTimeImmutable('@' . $input);

0 commit comments

Comments
 (0)