@@ -299,18 +299,65 @@ public static function move2trash($file_path, $ownerOnly = false) {
299299
300300 $ configuredTrashbinSize = static ::getConfiguredTrashbinSize ($ owner );
301301 if ($ configuredTrashbinSize >= 0 && $ sourceInfo ->getSize () >= $ configuredTrashbinSize ) {
302+ $ trashStorage ->releaseLock ($ trashInternalPath , ILockingProvider::LOCK_EXCLUSIVE , $ lockingProvider );
302303 return false ;
303304 }
304305
306+ // there is still a possibility that the file has been deleted by a remote user
307+ $ deletedBy = self ::overwriteDeletedBy ($ user );
308+
309+ $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
310+ $ query ->insert ('files_trash ' )
311+ ->setValue ('id ' , $ query ->createNamedParameter ($ filename ))
312+ ->setValue ('timestamp ' , $ query ->createNamedParameter ($ timestamp ))
313+ ->setValue ('location ' , $ query ->createNamedParameter ($ location ))
314+ ->setValue ('user ' , $ query ->createNamedParameter ($ owner ))
315+ ->setValue ('deleted_by ' , $ query ->createNamedParameter ($ deletedBy ));
316+ $ inserted = false ;
305317 try {
306- $ moveSuccessful = true ;
318+ $ inserted = ($ query ->executeStatement () === 1 );
319+ } catch (\Throwable $ e ) {
320+ Server::get (LoggerInterface::class)->error (
321+ 'trash bin database insert failed ' ,
322+ [
323+ 'app ' => 'files_trashbin ' ,
324+ 'exception ' => $ e ,
325+ 'user ' => $ owner ,
326+ 'filename ' => $ filename ,
327+ 'timestamp ' => $ timestamp ,
328+ ]
329+ );
330+ }
331+ if (!$ inserted ) {
332+ Server::get (LoggerInterface::class)->error (
333+ 'trash bin database couldn \'t be updated, skipping trash move ' ,
334+ [
335+ 'app ' => 'files_trashbin ' ,
336+ 'user ' => $ owner ,
337+ 'filename ' => $ filename ,
338+ 'timestamp ' => $ timestamp ,
339+ ]
340+ );
341+ $ trashStorage ->releaseLock ($ trashInternalPath , ILockingProvider::LOCK_EXCLUSIVE , $ lockingProvider );
342+ return false ;
343+ }
307344
345+ $ moveSuccessful = true ;
346+ try {
308347 $ inCache = $ sourceStorage ->getCache ()->inCache ($ sourceInternalPath );
309348 $ trashStorage ->moveFromStorage ($ sourceStorage , $ sourceInternalPath , $ trashInternalPath );
310349 if ($ inCache ) {
311350 $ trashStorage ->getUpdater ()->renameFromStorage ($ sourceStorage , $ sourceInternalPath , $ trashInternalPath );
351+ } else {
352+ $ sizeDifference = $ sourceInfo ->getSize ();
353+ if ($ sizeDifference < 0 ) {
354+ $ sizeDifference = null ;
355+ } else {
356+ $ sizeDifference = (int )$ sizeDifference ;
357+ }
358+ $ trashStorage ->getUpdater ()->update ($ trashInternalPath , null , $ sizeDifference );
312359 }
313- } catch (CopyRecursiveException $ e ) {
360+ } catch (\ Exception $ e ) {
314361 $ moveSuccessful = false ;
315362 if ($ trashStorage ->file_exists ($ trashInternalPath )) {
316363 $ trashStorage ->unlink ($ trashInternalPath );
@@ -331,24 +378,31 @@ public static function move2trash($file_path, $ownerOnly = false) {
331378 } else {
332379 $ trashStorage ->getUpdater ()->remove ($ trashInternalPath );
333380 }
334- return false ;
381+ $ moveSuccessful = false ;
335382 }
336383
337- if ($ moveSuccessful ) {
338- // there is still a possibility that the file has been deleted by a remote user
339- $ deletedBy = self ::overwriteDeletedBy ($ user );
340-
341- $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
342- $ query ->insert ('files_trash ' )
343- ->setValue ('id ' , $ query ->createNamedParameter ($ filename ))
344- ->setValue ('timestamp ' , $ query ->createNamedParameter ($ timestamp ))
345- ->setValue ('location ' , $ query ->createNamedParameter ($ location ))
346- ->setValue ('user ' , $ query ->createNamedParameter ($ owner ))
347- ->setValue ('deleted_by ' , $ query ->createNamedParameter ($ deletedBy ));
348- $ result = $ query ->executeStatement ();
349- if (!$ result ) {
350- Server::get (LoggerInterface::class)->error ('trash bin database couldn \'t be updated ' , ['app ' => 'files_trashbin ' ]);
384+ if (!$ moveSuccessful ) {
385+ Server::get (LoggerInterface::class)->error (
386+ 'trash move failed, removing trash metadata and payload ' ,
387+ [
388+ 'app ' => 'files_trashbin ' ,
389+ 'user ' => $ owner ,
390+ 'filename ' => $ filename ,
391+ 'timestamp ' => $ timestamp ,
392+ ]
393+ );
394+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
395+ if ($ trashStorage ->file_exists ($ trashInternalPath )) {
396+ if ($ trashStorage ->is_dir ($ trashInternalPath )) {
397+ $ trashStorage ->rmdir ($ trashInternalPath );
398+ } else {
399+ $ trashStorage ->unlink ($ trashInternalPath );
400+ }
351401 }
402+ $ trashStorage ->getUpdater ()->remove ($ trashInternalPath );
403+ }
404+
405+ if ($ moveSuccessful ) {
352406 Util::emitHook ('\OCA\Files_Trashbin\Trashbin ' , 'post_moveToTrash ' , ['filePath ' => Filesystem::normalizePath ($ file_path ),
353407 'trashPath ' => Filesystem::normalizePath (static ::getTrashFilename ($ filename , $ timestamp ))]);
354408
@@ -545,12 +599,7 @@ public static function restore($file, $filename, $timestamp) {
545599 self ::restoreVersions ($ view , $ file , $ filename , $ uniqueFilename , $ location , $ timestamp );
546600
547601 if ($ timestamp ) {
548- $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
549- $ query ->delete ('files_trash ' )
550- ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
551- ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
552- ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
553- $ query ->executeStatement ();
602+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
554603 }
555604
556605 return true ;
@@ -689,13 +738,6 @@ public static function delete($filename, $user, $timestamp = null) {
689738 $ size = 0 ;
690739
691740 if ($ timestamp ) {
692- $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
693- $ query ->delete ('files_trash ' )
694- ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
695- ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
696- ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
697- $ query ->executeStatement ();
698-
699741 $ file = static ::getTrashFilename ($ filename , $ timestamp );
700742 } else {
701743 $ file = $ filename ;
@@ -706,6 +748,9 @@ public static function delete($filename, $user, $timestamp = null) {
706748 try {
707749 $ node = $ userRoot ->get ('/files_trashbin/files/ ' . $ file );
708750 } catch (NotFoundException $ e ) {
751+ if ($ timestamp ) {
752+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
753+ }
709754 return $ size ;
710755 }
711756
@@ -719,9 +764,22 @@ public static function delete($filename, $user, $timestamp = null) {
719764 $ node ->delete ();
720765 self ::emitTrashbinPostDelete ('/files_trashbin/files/ ' . $ file );
721766
767+ if ($ timestamp ) {
768+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
769+ }
770+
722771 return $ size ;
723772 }
724773
774+ private static function deleteTrashRow (string $ user , string $ filename , int $ timestamp ): void {
775+ $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
776+ $ query ->delete ('files_trash ' )
777+ ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
778+ ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
779+ ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
780+ $ query ->executeStatement ();
781+ }
782+
725783 /**
726784 * @param string $file
727785 * @param string $filename
0 commit comments