diff options
Diffstat (limited to 'apps/files_trashbin')
11 files changed, 172 insertions, 29 deletions
diff --git a/apps/files_trashbin/composer/composer/InstalledVersions.php b/apps/files_trashbin/composer/composer/InstalledVersions.php index d50e0c9fcc4..41bc143c114 100644 --- a/apps/files_trashbin/composer/composer/InstalledVersions.php +++ b/apps/files_trashbin/composer/composer/InstalledVersions.php @@ -21,6 +21,8 @@ use Composer\Semver\VersionParser; * See also https://getcomposer.org/doc/07-runtime.md#installed-versions * * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final */ class InstalledVersions { diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php index dbafba14048..7ce7e565c83 100644 --- a/apps/files_trashbin/composer/composer/autoload_classmap.php +++ b/apps/files_trashbin/composer/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = $vendorDir; return array( @@ -43,4 +43,5 @@ return array( 'OCA\\Files_Trashbin\\Trash\\TrashItem' => $baseDir . '/../lib/Trash/TrashItem.php', 'OCA\\Files_Trashbin\\Trash\\TrashManager' => $baseDir . '/../lib/Trash/TrashManager.php', 'OCA\\Files_Trashbin\\Trashbin' => $baseDir . '/../lib/Trashbin.php', + 'OCA\\Files_Trashbin\\UserMigration\\TrashbinMigrator' => $baseDir . '/../lib/UserMigration/TrashbinMigrator.php', ); diff --git a/apps/files_trashbin/composer/composer/autoload_namespaces.php b/apps/files_trashbin/composer/composer/autoload_namespaces.php index 71c9e91858d..3f5c9296251 100644 --- a/apps/files_trashbin/composer/composer/autoload_namespaces.php +++ b/apps/files_trashbin/composer/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = $vendorDir; return array( diff --git a/apps/files_trashbin/composer/composer/autoload_psr4.php b/apps/files_trashbin/composer/composer/autoload_psr4.php index f7585c671e1..13d8f92a72c 100644 --- a/apps/files_trashbin/composer/composer/autoload_psr4.php +++ b/apps/files_trashbin/composer/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = $vendorDir; return array( diff --git a/apps/files_trashbin/composer/composer/autoload_real.php b/apps/files_trashbin/composer/composer/autoload_real.php index 35ef7fdcfa7..b9a42591b0c 100644 --- a/apps/files_trashbin/composer/composer/autoload_real.php +++ b/apps/files_trashbin/composer/composer/autoload_real.php @@ -23,20 +23,11 @@ class ComposerAutoloaderInitFiles_Trashbin } spl_autoload_register(array('ComposerAutoloaderInitFiles_Trashbin', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Trashbin', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader)); - } else { - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + \Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader)(); $loader->setClassMapAuthoritative(true); $loader->register(true); diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php index e759b34d356..2f6d1936a28 100644 --- a/apps/files_trashbin/composer/composer/autoload_static.php +++ b/apps/files_trashbin/composer/composer/autoload_static.php @@ -58,6 +58,7 @@ class ComposerStaticInitFiles_Trashbin 'OCA\\Files_Trashbin\\Trash\\TrashItem' => __DIR__ . '/..' . '/../lib/Trash/TrashItem.php', 'OCA\\Files_Trashbin\\Trash\\TrashManager' => __DIR__ . '/..' . '/../lib/Trash/TrashManager.php', 'OCA\\Files_Trashbin\\Trashbin' => __DIR__ . '/..' . '/../lib/Trashbin.php', + 'OCA\\Files_Trashbin\\UserMigration\\TrashbinMigrator' => __DIR__ . '/..' . '/../lib/UserMigration/TrashbinMigrator.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/files_trashbin/l10n/sv.js b/apps/files_trashbin/l10n/sv.js index 2a7da65340d..bad8f014050 100644 --- a/apps/files_trashbin/l10n/sv.js +++ b/apps/files_trashbin/l10n/sv.js @@ -13,7 +13,7 @@ OC.L10N.register( "Error while emptying trash bin" : "Fel vid tömning av papperskorgen", "Error while removing files from trash bin" : "Fel vid borttagning av filer från papperskorgen", "This operation is forbidden" : "Denna åtgärd är förbjuden", - "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, vänligen kontrollera loggarna eller kontakta administratören", + "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, kontrollera loggarna eller kontakta administratören", "No deleted files" : "Inga borttagna filer", "You will be able to recover deleted files from here" : "Du kommer kunna återskapa borttagna filer härifrån", "No entries found in this folder" : "Inga filer hittades i denna mapp", diff --git a/apps/files_trashbin/l10n/sv.json b/apps/files_trashbin/l10n/sv.json index 0ea84f83f8b..dcaf229bd4e 100644 --- a/apps/files_trashbin/l10n/sv.json +++ b/apps/files_trashbin/l10n/sv.json @@ -11,7 +11,7 @@ "Error while emptying trash bin" : "Fel vid tömning av papperskorgen", "Error while removing files from trash bin" : "Fel vid borttagning av filer från papperskorgen", "This operation is forbidden" : "Denna åtgärd är förbjuden", - "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, vänligen kontrollera loggarna eller kontakta administratören", + "This directory is unavailable, please check the logs or contact the administrator" : "Denna katalog är inte tillgänglig, kontrollera loggarna eller kontakta administratören", "No deleted files" : "Inga borttagna filer", "You will be able to recover deleted files from here" : "Du kommer kunna återskapa borttagna filer härifrån", "No entries found in this folder" : "Inga filer hittades i denna mapp", diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php index 5f56b9ba1ea..41466a865ac 100644 --- a/apps/files_trashbin/lib/AppInfo/Application.php +++ b/apps/files_trashbin/lib/AppInfo/Application.php @@ -30,17 +30,20 @@ use OCA\Files_Trashbin\Capabilities; use OCA\Files_Trashbin\Expiration; use OCA\Files_Trashbin\Trash\ITrashManager; use OCA\Files_Trashbin\Trash\TrashManager; -use OCP\App\IAppManager; +use OCA\Files_Trashbin\UserMigration\TrashbinMigrator; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; +use OCP\App\IAppManager; use OCP\ILogger; use OCP\IServerContainer; class Application extends App implements IBootstrap { + public const APP_ID = 'files_trashbin'; + public function __construct(array $urlParams = []) { - parent::__construct('files_trashbin', $urlParams); + parent::__construct(self::APP_ID, $urlParams); } public function register(IRegistrationContext $context): void { @@ -50,6 +53,8 @@ class Application extends App implements IBootstrap { $context->registerServiceAlias(ITrashManager::class, TrashManager::class); /** Register $principalBackend for the DAV collection */ $context->registerServiceAlias('principalBackend', Principal::class); + + $context->registerUserMigrator(TrashbinMigrator::class); } public function boot(IBootContext $context): void { @@ -65,10 +70,10 @@ class Application extends App implements IBootstrap { \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook'); \OCA\Files\App::getNavigationManager()->add(function () { - $l = \OC::$server->getL10N('files_trashbin'); + $l = \OC::$server->getL10N(self::APP_ID); return [ 'id' => 'trashbin', - 'appname' => 'files_trashbin', + 'appname' => self::APP_ID, 'script' => 'list.php', 'order' => 50, 'name' => $l->t('Deleted files'), diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index 6aec2f9821e..4631f9e9d5b 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -60,6 +60,7 @@ use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; +use Psr\Log\LoggerInterface; class Trashbin { @@ -227,7 +228,7 @@ class Trashbin { ->setValue('user', $query->createNamedParameter($user)); $result = $query->executeStatement(); if (!$result) { - \OC::$server->getLogger()->error('trash bin database couldn\'t be updated for the files owner', ['app' => 'files_trashbin']); + \OC::$server->get(LoggerInterface::class)->error('trash bin database couldn\'t be updated for the files owner', ['app' => 'files_trashbin']); } } } @@ -326,7 +327,7 @@ class Trashbin { if ($trashStorage->file_exists($trashInternalPath)) { $trashStorage->unlink($trashInternalPath); } - \OC::$server->getLogger()->error('Couldn\'t move ' . $file_path . ' to the trash bin', ['app' => 'files_trashbin']); + \OC::$server->get(LoggerInterface::class)->error('Couldn\'t move ' . $file_path . ' to the trash bin', ['app' => 'files_trashbin']); } if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort @@ -354,7 +355,7 @@ class Trashbin { ->setValue('user', $query->createNamedParameter($owner)); $result = $query->executeStatement(); if (!$result) { - \OC::$server->getLogger()->error('trash bin database couldn\'t be updated', ['app' => 'files_trashbin']); + \OC::$server->get(LoggerInterface::class)->error('trash bin database couldn\'t be updated', ['app' => 'files_trashbin']); } \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path), 'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)]); @@ -470,7 +471,7 @@ class Trashbin { if ($timestamp) { $location = self::getLocation($user, $filename, $timestamp); if ($location === false) { - \OC::$server->getLogger()->error('trash bin database inconsistent! ($user: ' . $user . ' $filename: ' . $filename . ', $timestamp: ' . $timestamp . ')', ['app' => 'files_trashbin']); + \OC::$server->get(LoggerInterface::class)->error('trash bin database inconsistent! ($user: ' . $user . ' $filename: ' . $filename . ', $timestamp: ' . $timestamp . ')', ['app' => 'files_trashbin']); } else { // if location no longer exists, restore file in the root directory if ($location !== '/' && @@ -870,7 +871,7 @@ class Trashbin { foreach ($files as $file) { if ($availableSpace < 0 && $expiration->isExpired($file['mtime'], true)) { $tmp = self::delete($file['name'], $user, $file['mtime']); - \OC::$server->getLogger()->info('remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', ['app' => 'files_trashbin']); + \OC::$server->get(LoggerInterface::class)->info('remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', ['app' => 'files_trashbin']); $availableSpace += $tmp; $size += $tmp; } else { @@ -901,9 +902,14 @@ class Trashbin { $size += self::delete($filename, $user, $timestamp); $count++; } catch (\OCP\Files\NotPermittedException $e) { - \OC::$server->getLogger()->logException($e, ['app' => 'files_trashbin', 'level' => \OCP\ILogger::WARN, 'message' => 'Removing "' . $filename . '" from trashbin failed.']); + \OC::$server->get(LoggerInterface::class)->warning('Removing "' . $filename . '" from trashbin failed.', + [ + 'exception' => $e, + 'app' => 'files_trashbin', + ] + ); } - \OC::$server->getLogger()->info( + \OC::$server->get(LoggerInterface::class)->info( 'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.', ['app' => 'files_trashbin'] ); @@ -999,7 +1005,7 @@ class Trashbin { $query = new CacheQueryBuilder( \OC::$server->getDatabaseConnection(), \OC::$server->getSystemConfig(), - \OC::$server->getLogger() + \OC::$server->get(LoggerInterface::class) ); $normalizedParentPath = ltrim(Filesystem::normalizePath(dirname('files_trashbin/versions/'. $filename)), '/'); $parentId = $cache->getId($normalizedParentPath); diff --git a/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php new file mode 100644 index 00000000000..0aa41c1954f --- /dev/null +++ b/apps/files_trashbin/lib/UserMigration/TrashbinMigrator.php @@ -0,0 +1,137 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com> + * + * @author Côme Chilliet <come.chilliet@nextcloud.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\Files_Trashbin\UserMigration; + +use OCA\Files_Trashbin\AppInfo\Application; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\IDBConnection; +use OCP\IUser; +use OCP\UserMigration\IExportDestination; +use OCP\UserMigration\IImportSource; +use OCP\UserMigration\IMigrator; +use OCP\UserMigration\TMigratorBasicVersionHandling; +use OCP\UserMigration\UserMigrationException; +use Symfony\Component\Console\Output\OutputInterface; + +class TrashbinMigrator implements IMigrator { + + use TMigratorBasicVersionHandling; + + protected const PATH_FILES_FOLDER = Application::APP_ID.'/files'; + protected const PATH_LOCATIONS_FILE = Application::APP_ID.'/locations.json'; + + protected IRootFolder $root; + + protected IDBConnection $dbc; + + public function __construct( + IRootFolder $rootFolder, + IDBConnection $dbc + ) { + $this->root = $rootFolder; + $this->dbc = $dbc; + } + + /** + * {@inheritDoc} + */ + public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void { + $output->writeln('Exporting trashbin into ' . Application::APP_ID . '…'); + + $uid = $user->getUID(); + + try { + $trashbinFolder = $this->root->get('/'.$uid.'/files_trashbin'); + if (!$trashbinFolder instanceof Folder) { + throw new UserMigrationException('Could not export trashbin, /'.$uid.'/files_trashbin is not a folder'); + } + $output->writeln("Exporting trashbin files…"); + if ($exportDestination->copyFolder($trashbinFolder, static::PATH_FILES_FOLDER) === false) { + throw new UserMigrationException("Could not export trashbin."); + } + $originalLocations = \OCA\Files_Trashbin\Trashbin::getLocations($uid); + if ($exportDestination->addFileContents(static::PATH_LOCATIONS_FILE, json_encode($originalLocations)) === false) { + throw new UserMigrationException("Could not export trashbin."); + } + } catch (NotFoundException $e) { + $output->writeln("No trashbin to export…"); + } + } + + /** + * {@inheritDoc} + */ + public function import(IUser $user, IImportSource $importSource, OutputInterface $output): void { + if ($importSource->getMigratorVersion(static::class) === null) { + $output->writeln('No version for ' . static::class . ', skipping import…'); + return; + } + + $output->writeln('Importing trashbin from ' . Application::APP_ID . '…'); + + $uid = $user->getUID(); + + if ($importSource->pathExists(static::PATH_FILES_FOLDER)) { + try { + $trashbinFolder = $this->root->get('/'.$uid.'/files_trashbin'); + if (!$trashbinFolder instanceof Folder) { + throw new UserMigrationException('Could not import trashbin, /'.$uid.'/files_trashbin is not a folder'); + } + } catch (NotFoundException $e) { + $trashbinFolder = $this->root->newFolder('/'.$uid.'/files_trashbin'); + } + $output->writeln("Importing trashbin files…"); + if ($importSource->copyToFolder($trashbinFolder, static::PATH_FILES_FOLDER) === false) { + throw new UserMigrationException("Could not import trashbin."); + } + $locations = json_decode($importSource->getFileContents(static::PATH_LOCATIONS_FILE), true, 512, JSON_THROW_ON_ERROR); + $qb = $this->dbc->getQueryBuilder(); + $qb->insert('files_trash') + ->values([ + 'id' => $qb->createParameter('id'), + 'timestamp' => $qb->createParameter('timestamp'), + 'location' => $qb->createParameter('location'), + 'user' => $qb->createNamedParameter($uid), + ]); + foreach ($locations as $id => $fileLocations) { + foreach ($fileLocations as $timestamp => $location) { + $qb + ->setParameter('id', $id) + ->setParameter('timestamp', $timestamp) + ->setParameter('location', $location) + ; + + $qb->executeStatement(); + } + } + } else { + $output->writeln("No trashbin to import…"); + } + } +} |