Skip to content

Commit 63de669

Browse files
committed
refactor: Commands and background jobs for the trashbin
- Use modern node and SetupManager API - Avoid passing the user by id and instead use IUser Signed-off-by: Carl Schwan <[email protected]>
1 parent a99c68d commit 63de669

File tree

11 files changed

+177
-157
lines changed

11 files changed

+177
-157
lines changed

apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private function getNextOffset(): int {
109109

110110
}
111111

112-
private function resetOffset() {
112+
private function resetOffset(): void {
113113
$this->runMutexOperation(function () {
114114
$this->appConfig->setValueInt(Application::APP_ID, self::OFFSET_CONFIG_KEY_NAME, 0);
115115
});

apps/files_trashbin/lib/Command/CleanUp.php

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,36 @@
77
*/
88
namespace OCA\Files_Trashbin\Command;
99

10+
use OC\Core\Command\Base;
11+
use OC\Files\SetupManager;
12+
use OC\User\LazyUser;
1013
use OCP\Files\IRootFolder;
14+
use OCP\Files\NotFoundException;
15+
use OCP\Files\NotPermittedException;
1116
use OCP\IDBConnection;
17+
use OCP\IUser;
1218
use OCP\IUserBackend;
1319
use OCP\IUserManager;
1420
use OCP\Util;
15-
use Symfony\Component\Console\Command\Command;
1621
use Symfony\Component\Console\Exception\InvalidOptionException;
1722
use Symfony\Component\Console\Input\InputArgument;
1823
use Symfony\Component\Console\Input\InputInterface;
1924
use Symfony\Component\Console\Input\InputOption;
2025
use Symfony\Component\Console\Output\OutputInterface;
2126

22-
class CleanUp extends Command {
27+
class CleanUp extends Base {
2328

2429
public function __construct(
2530
protected IRootFolder $rootFolder,
2631
protected IUserManager $userManager,
2732
protected IDBConnection $dbConnection,
33+
protected SetupManager $setupManager,
2834
) {
2935
parent::__construct();
3036
}
3137

3238
protected function configure() {
39+
parent::configure();
3340
$this
3441
->setName('trashbin:cleanup')
3542
->setDescription('Remove deleted files')
@@ -53,9 +60,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5360
throw new InvalidOptionException('Either specify a user_id or --all-users');
5461
} elseif (!empty($users)) {
5562
foreach ($users as $user) {
56-
if ($this->userManager->userExists($user)) {
63+
$userObject = $this->userManager->get($user);
64+
if ($userObject) {
5765
$output->writeln("Remove deleted files of <info>$user</info>");
58-
$this->removeDeletedFiles($user, $output, $verbose);
66+
$this->removeDeletedFiles($userObject, $output, $verbose);
5967
} else {
6068
$output->writeln("<error>Unknown user $user</error>");
6169
return 1;
@@ -75,7 +83,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7583
$users = $backend->getUsers('', $limit, $offset);
7684
foreach ($users as $user) {
7785
$output->writeln(" <info>$user</info>");
78-
$this->removeDeletedFiles($user, $output, $verbose);
86+
$userObject = new LazyUser($user, $this->userManager, null, $backend);
87+
$this->removeDeletedFiles($userObject, $output, $verbose);
7988
}
8089
$offset += $limit;
8190
} while (count($users) >= $limit);
@@ -89,30 +98,31 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8998
/**
9099
* remove deleted files for the given user
91100
*/
92-
protected function removeDeletedFiles(string $uid, OutputInterface $output, bool $verbose): void {
93-
\OC_Util::tearDownFS();
94-
\OC_Util::setupFS($uid);
95-
$path = '/' . $uid . '/files_trashbin';
96-
if ($this->rootFolder->nodeExists($path)) {
101+
protected function removeDeletedFiles(IUser $user, OutputInterface $output, bool $verbose): void {
102+
$this->setupManager->tearDown();
103+
$this->setupManager->setupForUser($user);
104+
$path = '/' . $user->getUID() . '/files_trashbin';
105+
try {
97106
$node = $this->rootFolder->get($path);
98-
99-
if ($verbose) {
100-
$output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
101-
}
102-
$node->delete();
103-
if ($this->rootFolder->nodeExists($path)) {
104-
$output->writeln('<error>Trash folder sill exists after attempting to delete it</error>');
105-
return;
106-
}
107-
$query = $this->dbConnection->getQueryBuilder();
108-
$query->delete('files_trash')
109-
->where($query->expr()->eq('user', $query->createParameter('uid')))
110-
->setParameter('uid', $uid);
111-
$query->executeStatement();
112-
} else {
107+
} catch (NotFoundException|NotPermittedException) {
113108
if ($verbose) {
114-
$output->writeln("No trash found for <info>$uid</info>");
109+
$output->writeln("No trash found for <info>{$user->getUID()}</info>");
115110
}
111+
return;
112+
}
113+
114+
if ($verbose) {
115+
$output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>{$user->getUID()}</info>.");
116+
}
117+
$node->delete();
118+
if ($this->rootFolder->nodeExists($path)) {
119+
$output->writeln('<error>Trash folder sill exists after attempting to delete it</error>');
120+
return;
116121
}
122+
$query = $this->dbConnection->getQueryBuilder();
123+
$query->delete('files_trash')
124+
->where($query->expr()->eq('user', $query->createParameter('uid')))
125+
->setParameter('uid', $user->getUID());
126+
$query->executeStatement();
117127
}
118128
}

apps/files_trashbin/lib/Command/Expire.php

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88
namespace OCA\Files_Trashbin\Command;
99

1010
use OC\Command\FileAccess;
11+
use OC\Files\SetupManager;
1112
use OCA\Files_Trashbin\Trashbin;
1213
use OCP\Command\ICommand;
14+
use OCP\Files\Folder;
15+
use OCP\Files\IRootFolder;
16+
use OCP\Files\NotFoundException;
17+
use OCP\Files\NotPermittedException;
18+
use OCP\IUser;
1319
use OCP\IUserManager;
1420
use OCP\Server;
1521

@@ -26,14 +32,35 @@ public function __construct(
2632

2733
public function handle() {
2834
$userManager = Server::get(IUserManager::class);
29-
if (!$userManager->userExists($this->user)) {
35+
$userObject = $userManager->get($this->user);
36+
if (!$userObject) {
3037
// User has been deleted already
3138
return;
3239
}
3340

34-
\OC_Util::tearDownFS();
35-
\OC_Util::setupFS($this->user);
36-
Trashbin::expire($this->user);
37-
\OC_Util::tearDownFS();
41+
$rootFolder = $this->getTrashRoot($userObject);
42+
if (!$rootFolder) {
43+
return;
44+
}
45+
46+
Trashbin::expire($rootFolder, $userObject);
47+
$setupManager = Server::get(SetupManager::class);
48+
$setupManager->tearDown();
49+
}
50+
51+
protected function getTrashRoot(IUser $user): ?Folder {
52+
$setupManager = Server::get(SetupManager::class);
53+
$rootFolder = Server::get(IRootFolder::class);
54+
$setupManager->tearDown();
55+
$setupManager->setupForUser($user);
56+
57+
try {
58+
/** @var Folder $folder */
59+
$folder = $rootFolder->getUserFolder($user->getUID())->getParent()->get('files_trashbin');
60+
return $folder;
61+
} catch (NotFoundException|NotPermittedException) {
62+
$setupManager->tearDown();
63+
return null;
64+
}
3865
}
3966
}

apps/files_trashbin/lib/Command/ExpireTrash.php

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,36 @@
77
*/
88
namespace OCA\Files_Trashbin\Command;
99

10-
use OC\Files\View;
10+
use OC\Core\Command\Base;
11+
use OC\Files\SetupManager;
1112
use OCA\Files_Trashbin\Expiration;
1213
use OCA\Files_Trashbin\Trashbin;
14+
use OCP\Files\Folder;
15+
use OCP\Files\IRootFolder;
16+
use OCP\Files\NotFoundException;
17+
use OCP\Files\NotPermittedException;
1318
use OCP\IUser;
1419
use OCP\IUserManager;
1520
use Psr\Log\LoggerInterface;
16-
use Symfony\Component\Console\Command\Command;
1721
use Symfony\Component\Console\Helper\ProgressBar;
1822
use Symfony\Component\Console\Input\InputArgument;
1923
use Symfony\Component\Console\Input\InputInterface;
2024
use Symfony\Component\Console\Output\OutputInterface;
2125

22-
class ExpireTrash extends Command {
26+
class ExpireTrash extends Base {
2327

24-
/**
25-
* @param IUserManager|null $userManager
26-
* @param Expiration|null $expiration
27-
*/
2828
public function __construct(
29-
private LoggerInterface $logger,
30-
private ?IUserManager $userManager = null,
31-
private ?Expiration $expiration = null,
29+
readonly private LoggerInterface $logger,
30+
readonly private ?IUserManager $userManager,
31+
readonly private ?Expiration $expiration,
32+
readonly private SetupManager $setupManager,
33+
readonly private IRootFolder $rootFolder,
3234
) {
3335
parent::__construct();
3436
}
3537

3638
protected function configure() {
39+
parent::configure();
3740
$this
3841
->setName('trashbin:expire')
3942
->setDescription('Expires the users trashbin')
@@ -81,31 +84,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int
8184

8285
public function expireTrashForUser(IUser $user) {
8386
try {
84-
$uid = $user->getUID();
85-
if (!$this->setupFS($uid)) {
87+
$trashRoot = $this->getTrashRoot($user);
88+
if (!$trashRoot) {
8689
return;
8790
}
88-
Trashbin::expire($uid);
91+
Trashbin::expire($trashRoot, $user);
8992
} catch (\Throwable $e) {
9093
$this->logger->error('Error while expiring trashbin for user ' . $user->getUID(), ['exception' => $e]);
9194
}
9295
}
9396

94-
/**
95-
* Act on behalf on trash item owner
96-
* @param string $user
97-
* @return boolean
98-
*/
99-
protected function setupFS($user) {
100-
\OC_Util::tearDownFS();
101-
\OC_Util::setupFS($user);
97+
protected function getTrashRoot(IUser $user): ?Folder {
98+
$this->setupManager->tearDown();
99+
$this->setupManager->setupForUser($user);
102100

103-
// Check if this user has a trashbin directory
104-
$view = new View('/' . $user);
105-
if (!$view->is_dir('/files_trashbin/files')) {
106-
return false;
101+
try {
102+
/** @var Folder $folder */
103+
$folder = $this->rootFolder->getUserFolder($user->getUID())->getParent()->get('files_trashbin');
104+
return $folder;
105+
} catch (NotFoundException|NotPermittedException) {
106+
return null;
107107
}
108-
109-
return true;
110108
}
111109
}

apps/files_trashbin/lib/Command/RestoreAllFiles.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
namespace OCA\Files_Trashbin\Command;
88

99
use OC\Core\Command\Base;
10+
use OC\Files\SetupManager;
1011
use OCA\Files_Trashbin\Trash\ITrashManager;
1112
use OCA\Files_Trashbin\Trash\TrashItem;
1213
use OCP\Files\IRootFolder;
1314
use OCP\IDBConnection;
1415
use OCP\IL10N;
1516
use OCP\IUserBackend;
1617
use OCP\IUserManager;
18+
use OCP\IUserSession;
1719
use OCP\L10N\IFactory;
1820
use Symfony\Component\Console\Exception\InvalidOptionException;
1921
use Symfony\Component\Console\Input\InputArgument;
@@ -48,6 +50,8 @@ public function __construct(
4850
protected IUserManager $userManager,
4951
protected IDBConnection $dbConnection,
5052
protected ITrashManager $trashManager,
53+
protected SetupManager $setupManager,
54+
protected IUserSession $userSession,
5155
IFactory $l10nFactory,
5256
) {
5357
parent::__construct();
@@ -140,17 +144,16 @@ protected function execute(InputInterface $input, OutputInterface $output): int
140144
* Restore deleted files for the given user according to the given filters
141145
*/
142146
protected function restoreDeletedFiles(string $uid, int $scope, ?int $since, ?int $until, bool $dryRun, OutputInterface $output): void {
143-
\OC_Util::tearDownFS();
144-
\OC_Util::setupFS($uid);
145-
\OC_User::setUserId($uid);
146-
147147
$user = $this->userManager->get($uid);
148-
149-
if ($user === null) {
148+
if (!$user) {
150149
$output->writeln("<error>Unknown user $uid</error>");
151150
return;
152151
}
153152

153+
$this->setupManager->tearDown();
154+
$this->setupManager->setupForUser($user);
155+
$this->userSession->setUser($user);
156+
154157
$userTrashItems = $this->filterTrashItems(
155158
$this->trashManager->listTrashRoot($user),
156159
$scope,

apps/files_trashbin/lib/Command/Size.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use OC\Core\Command\Base;
1212
use OCP\Command\IBus;
13+
use OCP\IAppConfig;
1314
use OCP\IConfig;
1415
use OCP\IUser;
1516
use OCP\IUserManager;
@@ -21,6 +22,7 @@
2122

2223
class Size extends Base {
2324
public function __construct(
25+
private IAppConfig $appConfig,
2426
private IConfig $config,
2527
private IUserManager $userManager,
2628
private IBus $commandBus,
@@ -55,7 +57,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5557
$this->config->setUserValue($user, 'files_trashbin', 'trashbin_size', (string)$parsedSize);
5658
$this->commandBus->push(new Expire($user));
5759
} else {
58-
$this->config->setAppValue('files_trashbin', 'trashbin_size', (string)$parsedSize);
60+
$this->appConfig->setValueInt('files_trashbin', 'trashbin_size', $parsedSize);
5961
$output->writeln('<info>Warning: changing the default trashbin size will automatically trigger cleanup of existing trashbins,</info>');
6062
$output->writeln('<info>a users trashbin can exceed the configured size until they move a new file to the trashbin.</info>');
6163
}
@@ -67,7 +69,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6769
}
6870

6971
private function printTrashbinSize(InputInterface $input, OutputInterface $output, ?string $user) {
70-
$globalSize = (int)$this->config->getAppValue('files_trashbin', 'trashbin_size', '-1');
72+
$globalSize = $this->appConfig->getValueInt('files_trashbin', 'trashbin_size', -1);
7173
if ($globalSize < 0) {
7274
$globalHumanSize = 'default (50% of available space)';
7375
} else {

apps/files_trashbin/lib/Listener/EventListener.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,38 @@
1515
use OCP\EventDispatcher\IEventListener;
1616
use OCP\Files\Events\BeforeFileSystemSetupEvent;
1717
use OCP\Files\Events\Node\NodeWrittenEvent;
18+
use OCP\Files\Folder;
19+
use OCP\Files\IRootFolder;
20+
use OCP\Files\NotFoundException;
21+
use OCP\Files\NotPermittedException;
22+
use OCP\IUserManager;
1823
use OCP\User\Events\BeforeUserDeletedEvent;
1924

2025
/** @template-implements IEventListener<NodeWrittenEvent|BeforeUserDeletedEvent|BeforeFileSystemSetupEvent> */
2126
class EventListener implements IEventListener {
2227
public function __construct(
28+
private IUserManager $userManager,
29+
private IRootFolder $rootFolder,
2330
private ?string $userId = null,
2431
) {
2532
}
2633

2734
public function handle(Event $event): void {
2835
if ($event instanceof NodeWrittenEvent) {
2936
// Resize trash
30-
if (!empty($this->userId)) {
31-
Trashbin::resizeTrash($this->userId);
37+
if (empty($this->userId)) {
38+
return;
39+
}
40+
try {
41+
/** @var Folder $trashRoot */
42+
$trashRoot = $this->rootFolder->get('/' . $this->userId . '/files_trashbin');
43+
} catch (NotFoundException|NotPermittedException) {
44+
return;
45+
}
46+
47+
$user = $this->userManager->get($this->userId);
48+
if ($user) {
49+
Trashbin::resizeTrash($trashRoot, $user);
3250
}
3351
}
3452

0 commit comments

Comments
 (0)