Skip to content

Commit b984cd1

Browse files
authored
Merge pull request #31575 from nextcloud/enh/add-trashbin-migrator
Add trashbin migrator to export and import trashbin data
2 parents 93d0c60 + 7fa8b2e commit b984cd1

File tree

4 files changed

+148
-4
lines changed

4 files changed

+148
-4
lines changed

apps/files_trashbin/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@
4343
'OCA\\Files_Trashbin\\Trash\\TrashItem' => $baseDir . '/../lib/Trash/TrashItem.php',
4444
'OCA\\Files_Trashbin\\Trash\\TrashManager' => $baseDir . '/../lib/Trash/TrashManager.php',
4545
'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php',
46+
'OCA\\Files_Trashbin\\UserMigration\\TrashbinMigrator' => $baseDir . '/../lib/UserMigration/TrashbinMigrator.php',
4647
);

apps/files_trashbin/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class ComposerStaticInitFiles_Trashbin
5858
'OCA\\Files_Trashbin\\Trash\\TrashItem' => __DIR__ . '/..' . '/../lib/Trash/TrashItem.php',
5959
'OCA\\Files_Trashbin\\Trash\\TrashManager' => __DIR__ . '/..' . '/../lib/Trash/TrashManager.php',
6060
'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php',
61+
'OCA\\Files_Trashbin\\UserMigration\\TrashbinMigrator' => __DIR__ . '/..' . '/../lib/UserMigration/TrashbinMigrator.php',
6162
);
6263

6364
public static function getInitializer(ClassLoader $loader)

apps/files_trashbin/lib/AppInfo/Application.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,20 @@
3030
use OCA\Files_Trashbin\Expiration;
3131
use OCA\Files_Trashbin\Trash\ITrashManager;
3232
use OCA\Files_Trashbin\Trash\TrashManager;
33-
use OCP\App\IAppManager;
33+
use OCA\Files_Trashbin\UserMigration\TrashbinMigrator;
3434
use OCP\AppFramework\App;
3535
use OCP\AppFramework\Bootstrap\IBootContext;
3636
use OCP\AppFramework\Bootstrap\IBootstrap;
3737
use OCP\AppFramework\Bootstrap\IRegistrationContext;
38+
use OCP\App\IAppManager;
3839
use OCP\ILogger;
3940
use OCP\IServerContainer;
4041

4142
class Application extends App implements IBootstrap {
43+
public const APP_ID = 'files_trashbin';
44+
4245
public function __construct(array $urlParams = []) {
43-
parent::__construct('files_trashbin', $urlParams);
46+
parent::__construct(self::APP_ID, $urlParams);
4447
}
4548

4649
public function register(IRegistrationContext $context): void {
@@ -50,6 +53,8 @@ public function register(IRegistrationContext $context): void {
5053
$context->registerServiceAlias(ITrashManager::class, TrashManager::class);
5154
/** Register $principalBackend for the DAV collection */
5255
$context->registerServiceAlias('principalBackend', Principal::class);
56+
57+
$context->registerUserMigrator(TrashbinMigrator::class);
5358
}
5459

5560
public function boot(IBootContext $context): void {
@@ -65,10 +70,10 @@ public function boot(IBootContext $context): void {
6570
\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
6671

6772
\OCA\Files\App::getNavigationManager()->add(function () {
68-
$l = \OC::$server->getL10N('files_trashbin');
73+
$l = \OC::$server->getL10N(self::APP_ID);
6974
return [
7075
'id' => 'trashbin',
71-
'appname' => 'files_trashbin',
76+
'appname' => self::APP_ID,
7277
'script' => 'list.php',
7378
'order' => 50,
7479
'name' => $l->t('Deleted files'),
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* @copyright Copyright (c) 2022 Côme Chilliet <[email protected]>
7+
*
8+
* @author Côme Chilliet <[email protected]>
9+
*
10+
* @license GNU AGPL version 3 or any later version
11+
*
12+
* This program is free software: you can redistribute it and/or modify
13+
* it under the terms of the GNU Affero General Public License as
14+
* published by the Free Software Foundation, either version 3 of the
15+
* License, or (at your option) any later version.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU Affero General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU Affero General Public License
23+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
24+
*
25+
*/
26+
27+
namespace OCA\Files_Trashbin\UserMigration;
28+
29+
use OCA\Files_Trashbin\AppInfo\Application;
30+
use OCP\Files\Folder;
31+
use OCP\Files\IRootFolder;
32+
use OCP\Files\NotFoundException;
33+
use OCP\IDBConnection;
34+
use OCP\IUser;
35+
use OCP\UserMigration\IExportDestination;
36+
use OCP\UserMigration\IImportSource;
37+
use OCP\UserMigration\IMigrator;
38+
use OCP\UserMigration\TMigratorBasicVersionHandling;
39+
use OCP\UserMigration\UserMigrationException;
40+
use Symfony\Component\Console\Output\OutputInterface;
41+
42+
class TrashbinMigrator implements IMigrator {
43+
44+
use TMigratorBasicVersionHandling;
45+
46+
protected const PATH_FILES_FOLDER = Application::APP_ID.'/files';
47+
protected const PATH_LOCATIONS_FILE = Application::APP_ID.'/locations.json';
48+
49+
protected IRootFolder $root;
50+
51+
protected IDBConnection $dbc;
52+
53+
public function __construct(
54+
IRootFolder $rootFolder,
55+
IDBConnection $dbc
56+
) {
57+
$this->root = $rootFolder;
58+
$this->dbc = $dbc;
59+
}
60+
61+
/**
62+
* {@inheritDoc}
63+
*/
64+
public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void {
65+
$output->writeln('Exporting trashbin into ' . Application::APP_ID . '');
66+
67+
$uid = $user->getUID();
68+
69+
try {
70+
$trashbinFolder = $this->root->get('/'.$uid.'/files_trashbin');
71+
if (!$trashbinFolder instanceof Folder) {
72+
throw new UserMigrationException('Could not export trashbin, /'.$uid.'/files_trashbin is not a folder');
73+
}
74+
$output->writeln("Exporting trashbin files…");
75+
if ($exportDestination->copyFolder($trashbinFolder, static::PATH_FILES_FOLDER) === false) {
76+
throw new UserMigrationException("Could not export trashbin.");
77+
}
78+
$originalLocations = \OCA\Files_Trashbin\Trashbin::getLocations($uid);
79+
if ($exportDestination->addFileContents(static::PATH_LOCATIONS_FILE, json_encode($originalLocations)) === false) {
80+
throw new UserMigrationException("Could not export trashbin.");
81+
}
82+
} catch (NotFoundException $e) {
83+
$output->writeln("No trashbin to export…");
84+
}
85+
}
86+
87+
/**
88+
* {@inheritDoc}
89+
*/
90+
public function import(IUser $user, IImportSource $importSource, OutputInterface $output): void {
91+
if ($importSource->getMigratorVersion(static::class) === null) {
92+
$output->writeln('No version for ' . static::class . ', skipping import…');
93+
return;
94+
}
95+
96+
$output->writeln('Importing trashbin from ' . Application::APP_ID . '');
97+
98+
$uid = $user->getUID();
99+
100+
if ($importSource->pathExists(static::PATH_FILES_FOLDER)) {
101+
try {
102+
$trashbinFolder = $this->root->get('/'.$uid.'/files_trashbin');
103+
if (!$trashbinFolder instanceof Folder) {
104+
throw new UserMigrationException('Could not import trashbin, /'.$uid.'/files_trashbin is not a folder');
105+
}
106+
} catch (NotFoundException $e) {
107+
$trashbinFolder = $this->root->newFolder('/'.$uid.'/files_trashbin');
108+
}
109+
$output->writeln("Importing trashbin files…");
110+
if ($importSource->copyToFolder($trashbinFolder, static::PATH_FILES_FOLDER) === false) {
111+
throw new UserMigrationException("Could not import trashbin.");
112+
}
113+
$locations = json_decode($importSource->getFileContents(static::PATH_LOCATIONS_FILE), true, 512, JSON_THROW_ON_ERROR);
114+
$qb = $this->dbc->getQueryBuilder();
115+
$qb->insert('files_trash')
116+
->values([
117+
'id' => $qb->createParameter('id'),
118+
'timestamp' => $qb->createParameter('timestamp'),
119+
'location' => $qb->createParameter('location'),
120+
'user' => $qb->createNamedParameter($uid),
121+
]);
122+
foreach ($locations as $id => $fileLocations) {
123+
foreach ($fileLocations as $timestamp => $location) {
124+
$qb
125+
->setParameter('id', $id)
126+
->setParameter('timestamp', $timestamp)
127+
->setParameter('location', $location)
128+
;
129+
130+
$qb->executeStatement();
131+
}
132+
}
133+
} else {
134+
$output->writeln("No trashbin to import…");
135+
}
136+
}
137+
}

0 commit comments

Comments
 (0)