refactor(trash): Port deletion code of Trashbin to node based API

Instead of using a mix of View and Node based file system manipulation,
use the 'new' node based API everywhere.

Replace the hooks used in the admin_audit related to the deletion to new
typed event that expose the deleted nodes.

And remove old calculateSize to get the size of the deleted folder and
instead rely on the Node::getSize information.

Signed-off-by: Carl Schwan <carl.schwan@nextclound.com>
Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
This commit is contained in:
Carl Schwan 2025-08-06 13:40:37 +02:00 committed by Carl Schwan
parent 057c0dcc98
commit ac029d1839
14 changed files with 255 additions and 150 deletions

View file

@ -11,7 +11,6 @@ return array(
'OCA\\AdminAudit\\Actions\\Files' => $baseDir . '/../lib/Actions/Files.php',
'OCA\\AdminAudit\\Actions\\Sharing' => $baseDir . '/../lib/Actions/Sharing.php',
'OCA\\AdminAudit\\Actions\\TagManagement' => $baseDir . '/../lib/Actions/TagManagement.php',
'OCA\\AdminAudit\\Actions\\Trashbin' => $baseDir . '/../lib/Actions/Trashbin.php',
'OCA\\AdminAudit\\Actions\\Versions' => $baseDir . '/../lib/Actions/Versions.php',
'OCA\\AdminAudit\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
'OCA\\AdminAudit\\AuditLogger' => $baseDir . '/../lib/AuditLogger.php',
@ -25,5 +24,6 @@ return array(
'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => $baseDir . '/../lib/Listener/GroupManagementEventListener.php',
'OCA\\AdminAudit\\Listener\\SecurityEventListener' => $baseDir . '/../lib/Listener/SecurityEventListener.php',
'OCA\\AdminAudit\\Listener\\SharingEventListener' => $baseDir . '/../lib/Listener/SharingEventListener.php',
'OCA\\AdminAudit\\Listener\\TrashbinEventListener' => $baseDir . '/../lib/Listener/TrashbinEventListener.php',
'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => $baseDir . '/../lib/Listener/UserManagementEventListener.php',
);

View file

@ -26,7 +26,6 @@ class ComposerStaticInitAdminAudit
'OCA\\AdminAudit\\Actions\\Files' => __DIR__ . '/..' . '/../lib/Actions/Files.php',
'OCA\\AdminAudit\\Actions\\Sharing' => __DIR__ . '/..' . '/../lib/Actions/Sharing.php',
'OCA\\AdminAudit\\Actions\\TagManagement' => __DIR__ . '/..' . '/../lib/Actions/TagManagement.php',
'OCA\\AdminAudit\\Actions\\Trashbin' => __DIR__ . '/..' . '/../lib/Actions/Trashbin.php',
'OCA\\AdminAudit\\Actions\\Versions' => __DIR__ . '/..' . '/../lib/Actions/Versions.php',
'OCA\\AdminAudit\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
'OCA\\AdminAudit\\AuditLogger' => __DIR__ . '/..' . '/../lib/AuditLogger.php',
@ -40,6 +39,7 @@ class ComposerStaticInitAdminAudit
'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/GroupManagementEventListener.php',
'OCA\\AdminAudit\\Listener\\SecurityEventListener' => __DIR__ . '/..' . '/../lib/Listener/SecurityEventListener.php',
'OCA\\AdminAudit\\Listener\\SharingEventListener' => __DIR__ . '/..' . '/../lib/Listener/SharingEventListener.php',
'OCA\\AdminAudit\\Listener\\TrashbinEventListener' => __DIR__ . '/..' . '/../lib/Listener/TrashbinEventListener.php',
'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/UserManagementEventListener.php',
);

View file

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\AdminAudit\Actions;
class Trashbin extends Action {
public function delete(array $params): void {
$this->log('File "%s" deleted from trash bin.',
['path' => $params['path']], ['path']
);
}
public function restore(array $params): void {
$this->log('File "%s" restored from trash bin.',
['path' => $params['filePath']], ['path']
);
}
}

View file

@ -26,7 +26,10 @@ use OCA\AdminAudit\Listener\FileEventListener;
use OCA\AdminAudit\Listener\GroupManagementEventListener;
use OCA\AdminAudit\Listener\SecurityEventListener;
use OCA\AdminAudit\Listener\SharingEventListener;
use OCA\AdminAudit\Listener\TrashbinEventListener;
use OCA\AdminAudit\Listener\UserManagementEventListener;
use OCA\Files_Trashbin\Events\BeforeNodeDeletedEvent as TrashbinBeforeNodeDeletedEvent;
use OCA\Files_Trashbin\Events\NodeRestoredEvent;
use OCA\Files_Versions\Events\VersionRestoredEvent;
use OCP\App\Events\AppDisableEvent;
use OCP\App\Events\AppEnableEvent;
@ -123,6 +126,10 @@ class Application extends App implements IBootstrap {
// Console events
$context->registerEventListener(ConsoleEvent::class, ConsoleEventListener::class);
// Trashbin events
$context->registerEventListener(TrashbinBeforeNodeDeletedEvent::class, TrashbinEventListener::class);
$context->registerEventListener(NodeRestoredEvent::class, TrashbinEventListener::class);
}
public function boot(IBootContext $context): void {
@ -144,7 +151,6 @@ class Application extends App implements IBootstrap {
$eventDispatcher = $serverContainer->get(IEventDispatcher::class);
$this->sharingLegacyHooks($logger);
$this->fileHooks($logger, $eventDispatcher);
$this->trashbinHooks($logger);
$this->versionsHooks($logger);
$this->tagHooks($logger, $eventDispatcher);
}
@ -216,10 +222,4 @@ class Application extends App implements IBootstrap {
$versionsActions = new Versions($logger);
Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete');
}
private function trashbinHooks(IAuditLogger $logger): void {
$trashActions = new Trashbin($logger);
Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete');
Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore');
}
}

View file

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\AdminAudit\Listener;
use OCA\AdminAudit\Actions\Action;
use OCA\Files_Trashbin\Events\BeforeNodeDeletedEvent;
use OCA\Files_Trashbin\Events\NodeRestoredEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
/**
* @template-implements IEventListener<BeforeNodeDeletedEvent|NodeRestoredEvent>
*/
class TrashbinEventListener extends Action implements IEventListener {
public function handle(Event $event): void {
if ($event instanceof BeforeNodeDeletedEvent) {
$this->log('File "%s" deleted from trash bin.',
['path' => $event->getSource()->getPath()], ['path']
);
} elseif ($event instanceof NodeRestoredEvent) {
$this->log('File "%s" restored from trash bin.',
['path' => $event->getTarget()->getPath()], ['path']
);
}
}
}

View file

@ -16,8 +16,12 @@ return array(
'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => $baseDir . '/../lib/Command/RestoreAllFiles.php',
'OCA\\Files_Trashbin\\Command\\Size' => $baseDir . '/../lib/Command/Size.php',
'OCA\\Files_Trashbin\\Controller\\PreviewController' => $baseDir . '/../lib/Controller/PreviewController.php',
'OCA\\Files_Trashbin\\Events\\BeforeDeleteAllEvent' => $baseDir . '/../lib/Events/BeforeDeleteAllEvent.php',
'OCA\\Files_Trashbin\\Events\\BeforeNodeDeletedEvent' => $baseDir . '/../lib/Events/BeforeNodeDeletedEvent.php',
'OCA\\Files_Trashbin\\Events\\BeforeNodeRestoredEvent' => $baseDir . '/../lib/Events/BeforeNodeRestoredEvent.php',
'OCA\\Files_Trashbin\\Events\\DeleteAllEvent' => $baseDir . '/../lib/Events/DeleteAllEvent.php',
'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => $baseDir . '/../lib/Events/MoveToTrashEvent.php',
'OCA\\Files_Trashbin\\Events\\NodeDeletedEvent' => $baseDir . '/../lib/Events/NodeDeletedEvent.php',
'OCA\\Files_Trashbin\\Events\\NodeRestoredEvent' => $baseDir . '/../lib/Events/NodeRestoredEvent.php',
'OCA\\Files_Trashbin\\Exceptions\\CopyRecursiveException' => $baseDir . '/../lib/Exceptions/CopyRecursiveException.php',
'OCA\\Files_Trashbin\\Expiration' => $baseDir . '/../lib/Expiration.php',

View file

@ -31,8 +31,12 @@ class ComposerStaticInitFiles_Trashbin
'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => __DIR__ . '/..' . '/../lib/Command/RestoreAllFiles.php',
'OCA\\Files_Trashbin\\Command\\Size' => __DIR__ . '/..' . '/../lib/Command/Size.php',
'OCA\\Files_Trashbin\\Controller\\PreviewController' => __DIR__ . '/..' . '/../lib/Controller/PreviewController.php',
'OCA\\Files_Trashbin\\Events\\BeforeDeleteAllEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeDeleteAllEvent.php',
'OCA\\Files_Trashbin\\Events\\BeforeNodeDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeNodeDeletedEvent.php',
'OCA\\Files_Trashbin\\Events\\BeforeNodeRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/BeforeNodeRestoredEvent.php',
'OCA\\Files_Trashbin\\Events\\DeleteAllEvent' => __DIR__ . '/..' . '/../lib/Events/DeleteAllEvent.php',
'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => __DIR__ . '/..' . '/../lib/Events/MoveToTrashEvent.php',
'OCA\\Files_Trashbin\\Events\\NodeDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/NodeDeletedEvent.php',
'OCA\\Files_Trashbin\\Events\\NodeRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/NodeRestoredEvent.php',
'OCA\\Files_Trashbin\\Exceptions\\CopyRecursiveException' => __DIR__ . '/..' . '/../lib/Exceptions/CopyRecursiveException.php',
'OCA\\Files_Trashbin\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php',

View file

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Trashbin\Events;
use OCP\EventDispatcher\Event;
use OCP\Files\Node;
/**
* Event send before emptying the trash.
* @since 32.0.0
*/
class BeforeDeleteAllEvent extends Event {
/**
* @param Node[] $deletedNodes
*/
public function __construct(
private readonly array $deletedNodes,
) {
parent::__construct();
}
/** @return Node[] */
public function getDeletedNodes(): array {
return $this->deletedNodes;
}
}

View file

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Trashbin\Events;
use OCP\EventDispatcher\Event;
use OCP\Files\Node;
/**
* Event send before a node is deleted definitively.
* @since 32.0.0
*/
class BeforeNodeDeletedEvent extends Event {
public function __construct(
private readonly Node $source,
) {
parent::__construct();
}
public function getSource(): Node {
return $this->source;
}
}

View file

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Trashbin\Events;
use OCP\EventDispatcher\Event;
use OCP\Files\Node;
/**
* Event send before emptying the trash.
* @since 32.0.0
*/
class DeleteAllEvent extends Event {
/**
* @param Node[] $deletedNodes
*/
public function __construct(
private readonly array $deletedNodes,
) {
parent::__construct();
}
/** @return Node[] */
public function getDeletedNodes(): array {
return $this->deletedNodes;
}
}

View file

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Trashbin\Events;
use OCP\EventDispatcher\Event;
use OCP\Files\Node;
/**
* Event send before a node is deleted definitively.
* @since 32.0.0
*/
class NodeDeletedEvent extends Event {
public function __construct(
readonly private Node $source,
) {
parent::__construct();
}
public function getSource(): Node {
return $this->source;
}
}

View file

@ -19,7 +19,6 @@ use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
class TrashRoot implements ICollection {
public function __construct(
private IUser $user,
private ITrashManager $trashManager,
@ -31,7 +30,7 @@ class TrashRoot implements ICollection {
throw new Forbidden('Not allowed to delete items from the trash bin');
}
Trashbin::deleteAll();
Trashbin::deleteAll($this->user);
foreach ($this->trashManager->listTrashRoot($this->user) as $trashItem) {
$this->trashManager->removeItem($trashItem);
}
@ -67,6 +66,7 @@ class TrashRoot implements ICollection {
}
public function getChild($name): ITrash {
/** @var list<ITrash&ICollection> $entries */
$entries = $this->getChildren();
foreach ($entries as $entry) {

View file

@ -18,7 +18,9 @@ use OC\User\NoUserException;
use OC_User;
use OCA\Files_Trashbin\AppInfo\Application;
use OCA\Files_Trashbin\Command\Expire;
use OCA\Files_Trashbin\Events\BeforeDeleteAllEvent;
use OCA\Files_Trashbin\Events\BeforeNodeRestoredEvent;
use OCA\Files_Trashbin\Events\DeleteAllEvent;
use OCA\Files_Trashbin\Events\NodeRestoredEvent;
use OCA\Files_Trashbin\Exceptions\CopyRecursiveException;
use OCA\Files_Versions\Storage;
@ -42,6 +44,7 @@ use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
@ -590,47 +593,50 @@ class Trashbin implements IEventListener {
/**
* delete all files from the trash
*/
public static function deleteAll() {
$user = OC_User::getUser();
$userRoot = \OC::$server->getUserFolder($user)->getParent();
$view = new View('/' . $user);
$fileInfos = $view->getDirectoryContent('files_trashbin/files');
public static function deleteAll(IUser $user) {
$rootFolder = Server::get(IRootFolder::class);
$dispatcher = Server::get(IEventDispatcher::class);
$dbConnection = Server::get(IDBConnection::class);
$userRoot = $rootFolder->getUserFolder($user->getUID())->getParent();
try {
$trash = $userRoot->get('files_trashbin');
} catch (NotFoundException $e) {
/** @var Folder $trashRoot */
$trashRoot = $userRoot->get('files_trashbin');
/** @var Folder $trashFilesRoot */
$trashFilesRoot = $trashRoot->get('files');
} catch (NotFoundException) {
return false;
} catch (NotPermittedException) {
return false;
}
// Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore)
$filePaths = [];
foreach ($fileInfos as $fileInfo) {
$filePaths[] = $view->getRelativePath($fileInfo->getPath());
}
unset($fileInfos); // save memory
// Bulk PreDelete-Hook
\OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', ['paths' => $filePaths]);
$trashNodes = $trashFilesRoot->getDirectoryListing();
$beforeDeleteAllEvent = new BeforeDeleteAllEvent($trashNodes);
$dispatcher->dispatchTyped($beforeDeleteAllEvent);
// Single-File Hooks
foreach ($filePaths as $path) {
self::emitTrashbinPreDelete($path);
foreach ($trashNodes as $trashNode) {
$event = new Events\BeforeNodeDeletedEvent($trashNode);
$dispatcher->dispatchTyped($event);
}
// actual file deletion
$trash->delete();
$trashRoot->delete();
$query = Server::get(IDBConnection::class)->getQueryBuilder();
$query = $dbConnection->getQueryBuilder();
$query->delete('files_trash')
->where($query->expr()->eq('user', $query->createNamedParameter($user)));
->where($query->expr()->eq('user', $query->createNamedParameter($user->getUID())));
$query->executeStatement();
// Bulk PostDelete-Hook
\OC_Hook::emit('\OCP\Trashbin', 'deleteAll', ['paths' => $filePaths]);
$deleteAllEvent = new DeleteAllEvent($trashNodes);
$dispatcher->dispatchTyped($deleteAllEvent);
// Single-File Hooks
foreach ($filePaths as $path) {
self::emitTrashbinPostDelete($path);
foreach ($trashNodes as $trashNode) {
$event = new Events\NodeDeletedEvent($trashNode);
$dispatcher->dispatchTyped($event);
}
$trash = $userRoot->newFolder('files_trashbin');
@ -640,39 +646,31 @@ class Trashbin implements IEventListener {
}
/**
* wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted
*
* @param string $path
*/
protected static function emitTrashbinPreDelete($path) {
\OC_Hook::emit('\OCP\Trashbin', 'preDelete', ['path' => $path]);
}
/**
* wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted
*
* @param string $path
*/
protected static function emitTrashbinPostDelete($path) {
\OC_Hook::emit('\OCP\Trashbin', 'delete', ['path' => $path]);
}
/**
* delete file from trash bin permanently
* Delete file from trash bin permanently
*
* @param string $filename path to the file
* @param string $user
* @param int $timestamp of deletion time
*
* @param ?int $timestamp of deletion time
* @return int|float size of deleted files
*/
public static function delete($filename, $user, $timestamp = null) {
$userRoot = \OC::$server->getUserFolder($user)->getParent();
$view = new View('/' . $user);
public static function delete(string $filename, string $user, ?int $timestamp = null): int|float {
$rootFolder = Server::get(IRootFolder::class);
$appManager = Server::get(IAppManager::class);
$dispatcher = Server::get(IEventDispatcher::class);
$dbConnection = Server::get(IDBConnection::class);
$userRoot = $rootFolder->getUserFolder($user)->getParent();
try {
/** @var Folder $trashRoot */
$trashRoot = $userRoot->get('files_trashbin');
} catch (NotFoundException|NotPermittedException) {
return 0;
}
$size = 0;
if ($timestamp) {
$query = Server::get(IDBConnection::class)->getQueryBuilder();
$query = $dbConnection->getQueryBuilder();
$query->delete('files_trash')
->where($query->expr()->eq('user', $query->createNamedParameter($user)))
->andWhere($query->expr()->eq('id', $query->createNamedParameter($filename)))
@ -684,48 +682,52 @@ class Trashbin implements IEventListener {
$file = $filename;
}
$size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
if ($appManager->isEnabledForUser('files_versions')) {
size += Trashbin::deleteVersions($trashRoot, $file, $filename, $timestamp, $user);
}
try {
$node = $userRoot->get('/files_trashbin/files/' . $file);
} catch (NotFoundException $e) {
} catch (NotFoundException) {
return $size;
}
if ($node instanceof Folder) {
$size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file));
} elseif ($node instanceof File) {
$size += $view->filesize('/files_trashbin/files/' . $file);
}
$size += $node->getSize();
$event = new Events\BeforeNodeDeletedEvent($node);
$dispatcher->dispatchTyped($event);
self::emitTrashbinPreDelete('/files_trashbin/files/' . $file);
$node->delete();
self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
$event = new Events\NodeDeletedEvent($node);
$dispatcher->dispatchTyped($event);
return $size;
}
/**
* @param string $file
* @param string $filename
* @param ?int $timestamp
* Delete version files corresponding to a given file from trash bin permanently.
*/
private static function deleteVersions(View $view, $file, $filename, $timestamp, string $user): int|float {
private static function deleteVersions(Folder $trashRoot, string $file, string $filename, ?int $timestamp, string $user): int|float {
$size = 0;
if (Server::get(IAppManager::class)->isEnabledForUser('files_versions')) {
if ($view->is_dir('files_trashbin/versions/' . $file)) {
$size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file));
$view->unlink('files_trashbin/versions/' . $file);
} elseif ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
foreach ($versions as $v) {
if ($timestamp) {
$size += $view->filesize('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp));
$view->unlink('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp));
} else {
$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v);
$view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v);
}
try {
$fileVersion = $trashRoot->get('versions/' . $file);
} catch (NotFoundException) {
}
if ($fileVersion) {
$size += $fileVersion->getSize();
$fileVersion->delete();
} elseif ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
foreach ($versions as $v) {
if ($timestamp) {
$node = $trashRoot->get('/files_trashbin/versions/' . static::getTrashFilename($filename . '.v' . $v, $timestamp));
} else {
$node = $trashRoot->get('/files_trashbin/versions/' . $filename . '.v' . $v);
}
$size += $node->getSize();
$node->delete();
}
}
return $size;
@ -1078,37 +1080,6 @@ class Trashbin implements IEventListener {
return $filename;
}
/**
* get the size from a given root folder
*
* @param View $view file view on the root folder
* @return int|float size of the folder
*/
private static function calculateSize(View $view): int|float {
$root = Server::get(IConfig::class)->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
if (!file_exists($root)) {
return 0;
}
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST);
$size = 0;
/**
* RecursiveDirectoryIterator on an NFS path isn't iterable with foreach
* This bug is fixed in PHP 5.5.9 or before
* See #8376
*/
$iterator->rewind();
while ($iterator->valid()) {
$path = $iterator->current();
$relpath = substr($path, strlen($root) - 1);
if (!$view->is_dir($relpath)) {
$size += $view->filesize($relpath);
}
$iterator->next();
}
return $size;
}
/**
* get current size of trash bin from a given user
*

View file

@ -11,8 +11,6 @@
<code><![CDATA[ManagerEvent::EVENT_CREATE]]></code>
</DeprecatedConstant>
<DeprecatedMethod>
<code><![CDATA[Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore')]]></code>
<code><![CDATA[Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete')]]></code>
<code><![CDATA[Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete')]]></code>
<code><![CDATA[Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate')]]></code>
<code><![CDATA[Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword')]]></code>
@ -1644,14 +1642,6 @@
<code><![CDATA[INode]]></code>
</MismatchingDocblockReturnType>
</file>
<file src="apps/files_trashbin/lib/Sabre/TrashRoot.php">
<InvalidReturnStatement>
<code><![CDATA[$entry]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[ITrash]]></code>
</InvalidReturnType>
</file>
<file src="apps/files_trashbin/lib/Storage.php">
<DeprecatedMethod>
<code><![CDATA[dispatch]]></code>