Skip to content

Commit 3bb2dce

Browse files
committed
better UX to manage external folders from occ
1 parent 22e7332 commit 3bb2dce

File tree

4 files changed

+173
-25
lines changed

4 files changed

+173
-25
lines changed

lib/Command/ExternalAdd.php

Lines changed: 137 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@
3333

3434

3535
use OC\Core\Command\Base;
36-
use OCA\Backup\Db\ExternalFolderRequest;
37-
use OCA\Backup\Model\ExternalFolder;
38-
use Symfony\Component\Console\Input\InputArgument;
36+
use OCA\Backup\Exceptions\ExternalFolderNotFoundException;
37+
use OCA\Backup\Service\ExternalFolderService;
38+
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
39+
use OCP\Files\StorageNotAvailableException;
3940
use Symfony\Component\Console\Input\InputInterface;
4041
use Symfony\Component\Console\Output\OutputInterface;
42+
use Symfony\Component\Console\Question\ChoiceQuestion;
43+
use Symfony\Component\Console\Question\ConfirmationQuestion;
44+
use Symfony\Component\Console\Question\Question;
4145

4246

4347
/**
@@ -48,19 +52,19 @@
4852
class ExternalAdd extends Base {
4953

5054

51-
/** @var ExternalFolderRequest */
52-
private $externalFolderRequest;
55+
/** @var ExternalFolderService */
56+
private $externalFolderService;
5357

5458

5559
/**
5660
* ExternalAdd constructor.
5761
*
58-
* @param ExternalFolderRequest $externalFolderRequest
62+
* @param ExternalFolderService $externalFolderService
5963
*/
60-
public function __construct(ExternalFolderRequest $externalFolderRequest) {
64+
public function __construct(ExternalFolderService $externalFolderService) {
6165
parent::__construct();
6266

63-
$this->externalFolderRequest = $externalFolderRequest;
67+
$this->externalFolderService = $externalFolderService;
6468
}
6569

6670

@@ -69,9 +73,7 @@ public function __construct(ExternalFolderRequest $externalFolderRequest) {
6973
*/
7074
protected function configure() {
7175
$this->setName('backup:external:add')
72-
->setDescription('Add external filesystem to store your backups')
73-
->addArgument('storage_id', InputArgument::REQUIRED, 'storage_id from oc_storage')
74-
->addArgument('root', InputArgument::REQUIRED, 'folder');
76+
->setDescription('Add external filesystem to store your backups');
7577
}
7678

7779

@@ -80,19 +82,137 @@ protected function configure() {
8082
* @param OutputInterface $output
8183
*
8284
* @return int
85+
* @throws InsufficientDataForMeaningfulAnswerException
86+
* @throws StorageNotAvailableException
87+
* @throws ExternalFolderNotFoundException
8388
*/
8489
protected function execute(InputInterface $input, OutputInterface $output): int {
85-
$storageId = (int)$input->getArgument('storage_id');
86-
$root = $input->getArgument('root');
8790

88-
$folder = new ExternalFolder();
89-
$folder->setStorageId($storageId);
90-
$folder->setRoot($root);
91+
$storageId = $this->selectStorage($input, $output);
92+
$output->writeln('');
93+
if ($storageId === 0) {
94+
$output->writeln('Operation cancelled');
9195

92-
$this->externalFolderRequest->save($folder);
96+
return 0;
97+
}
98+
99+
$root = $this->requestingRoot($input, $output);
100+
echo '>> ' . json_encode($root);
101+
$output->writeln('');
102+
if ($root === '') {
103+
$output->writeln('Operation cancelled');
104+
105+
return 0;
106+
}
107+
108+
$external = $this->externalFolderService->getStorageById($storageId);
109+
$output->writeln('');
110+
if ($external->getRoot() !== '') {
111+
$output->writeln('This external filesystem is already used by the Backup App');
112+
113+
return 0;
114+
}
115+
116+
$external->setRoot($root);
117+
118+
$output->writeln('Please confirm the creation of a new External Folder, based on this setup:');
119+
$output->writeln('');
120+
$output->writeln('Storage Id: <info>' . $external->getStorageId() . '</info>');
121+
$output->writeln('Storage Path: <info>' . $external->getStorage() . '</info>');
122+
$output->writeln('Localisation of backup files: <info>' . $external->getRoot() . '</info>');
123+
$output->writeln('');
124+
125+
$question = new ConfirmationQuestion(
126+
'<comment>Do you really want to create and use this External Folder to store your backup ?</comment> (y/N) ',
127+
false,
128+
'/^(y|Y)/i'
129+
);
130+
131+
$helper = $this->getHelper('question');
132+
if (!$helper->ask($input, $output, $question)) {
133+
$output->writeln('Operation cancelled');
134+
135+
return 0;
136+
}
137+
138+
$this->externalFolderService->save($external);
139+
140+
$output->writeln(
141+
'<info>The generated External Folder will now be used to store your restoring points</info>'
142+
);
143+
144+
return 0;
145+
}
146+
147+
148+
/**
149+
* @param InputInterface $input
150+
* @param OutputInterface $output
151+
*
152+
* @return int|mixed|string|null
153+
* @throws InsufficientDataForMeaningfulAnswerException
154+
* @throws StorageNotAvailableException
155+
*/
156+
private function selectStorage(InputInterface $input, OutputInterface $output): int {
157+
$availableStorage = [];
158+
foreach ($this->externalFolderService->getStorages() as $storage) {
159+
if ($storage->getRoot() !== '') {
160+
continue;
161+
}
162+
$availableStorage[$storage->getStorageId()] =
163+
$storage->getStorage() . ' (id:' . $storage->getStorageId() . ')';
164+
}
165+
166+
if (empty($availableStorage)) {
167+
$output->writeln('There is no available external filesystem.');
168+
$output->writeln(
169+
'You can use <info>./occ backup:external:list</info> to see already configured external folders'
170+
);
171+
$output->writeln('You can use the <info>Files External</info> to add a new external filesystem');
172+
$output->writeln('');
173+
174+
return 0;
175+
}
176+
177+
$availableStorage[0] = 'exit';
178+
179+
$output->writeln('');
180+
$helper = $this->getHelper('question');
181+
$question = new ChoiceQuestion(
182+
'Which external storage you want to use to store your backups ?',
183+
$availableStorage,
184+
0
185+
);
186+
$question->setErrorMessage('Select a valid filesystem');
187+
188+
$result = $helper->ask($input, $output, $question);
189+
foreach ($availableStorage as $k => $v) {
190+
if ($v === $result) {
191+
return $k;
192+
}
193+
}
93194

94195
return 0;
95196
}
96197

198+
199+
/**
200+
* @param InputInterface $input
201+
* @param OutputInterface $output
202+
*
203+
* @return string
204+
*/
205+
private function requestingRoot(InputInterface $input, OutputInterface $output): string {
206+
$helper = $this->getHelper('question');
207+
$default = 'backup/points/';
208+
209+
$question = new Question(
210+
'Path to the right folder to store your backups (default="<info>' . $default . '</info>"): ',
211+
$default
212+
);
213+
214+
return trim($helper->ask($input, $output, $question));
215+
}
216+
97217
}
98218

lib/Command/ExternalList.php

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
namespace OCA\Backup\Command;
3333

3434

35+
use Exception;
3536
use OC\Core\Command\Base;
36-
use OCA\Backup\Db\ExternalFolderRequest;
37+
use OCA\Backup\Service\ExternalFolderService;
3738
use Symfony\Component\Console\Helper\Table;
3839
use Symfony\Component\Console\Input\InputInterface;
3940
use Symfony\Component\Console\Output\ConsoleOutput;
@@ -48,17 +49,17 @@
4849
class ExternalList extends Base {
4950

5051

51-
/** @var ExternalFolderRequest */
52-
private $externalFolderRequest;
52+
/** @var ExternalFolderService */
53+
private $externalFolderService;
5354

5455

5556
/**
5657
* ExternalList constructor.
5758
*
58-
* @param ExternalFolderRequest $externalFolderRequest
59+
* @param ExternalFolderService $externalFolderService
5960
*/
60-
public function __construct(ExternalFolderRequest $externalFolderRequest) {
61-
$this->externalFolderRequest = $externalFolderRequest;
61+
public function __construct(ExternalFolderService $externalFolderService) {
62+
$this->externalFolderService = $externalFolderService;
6263

6364
parent::__construct();
6465
}
@@ -83,13 +84,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8384
$output = new ConsoleOutput();
8485
$output = $output->section();
8586
$table = new Table($output);
86-
$table->setHeaders(['StorageId', 'Storage Folder']);
87+
$table->setHeaders(['StorageId', 'Path', 'Storage Folder']);
8788
$table->render();
8889

89-
foreach ($this->externalFolderRequest->getAll() as $externalFolder) {
90+
foreach ($this->externalFolderService->getAll() as $externalFolder) {
91+
$storagePath = '';
92+
try {
93+
$storage = $this->externalFolderService->getStorageById($externalFolder->getStorageId());
94+
$storagePath = $storage->getStorage();
95+
} catch (Exception $e) {
96+
}
97+
9098
$table->appendRow(
9199
[
92100
$externalFolder->getStorageId(),
101+
$storagePath,
93102
$externalFolder->getRoot()
94103
]
95104
);

lib/Controller/LocalController.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ public function getRestoringPoints(): DataResponse {
156156
return new DataResponse($points);
157157
}
158158

159+
159160
/**
160161
* @return DataResponse
161162
*/

lib/Service/ExternalFolderService.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,24 @@ public function getStorages(): array {
849849
return $externals;
850850
}
851851

852+
/**
853+
* @param int $storageId
854+
*
855+
* @return ExternalFolder
856+
* @throws InsufficientDataForMeaningfulAnswerException
857+
* @throws StorageNotAvailableException
858+
* @throws ExternalFolderNotFoundException
859+
*/
860+
public function getStorageById(int $storageId): ExternalFolder {
861+
foreach ($this->getStorages() as $external) {
862+
if ($external->getStorageId() === $storageId) {
863+
return $external;
864+
}
865+
}
866+
867+
throw new ExternalFolderNotFoundException();
868+
}
869+
852870

853871
/**
854872
* Construct the storage implementation

0 commit comments

Comments
 (0)