Implement a cleanup on file delete
authorAlexander Ebert <ebert@woltlab.com>
Fri, 3 May 2024 15:23:48 +0000 (17:23 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 8 Jun 2024 10:19:39 +0000 (12:19 +0200)
wcfsetup/install/files/lib/data/attachment/AttachmentEditor.class.php
wcfsetup/install/files/lib/data/file/FileAction.class.php
wcfsetup/install/files/lib/system/file/processor/AttachmentFileProcessor.class.php
wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php
wcfsetup/install/files/lib/system/file/processor/IFileProcessor.class.php
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeImg.class.php

index 311dc7d080f6c82c749463e6216b42706a5ac139..51915bdd7cd8bad8a08be9f1cb4bba175f3bc8d1 100644 (file)
@@ -64,6 +64,10 @@ class AttachmentEditor extends DatabaseObjectEditor
      */
     public function deleteFiles()
     {
+        if ($this->fileID !== null) {
+            return;
+        }
+
         @\unlink($this->getLocation());
         if ($this->tinyThumbnailType) {
             @\unlink($this->getTinyThumbnailLocation());
index 05a54e321228998c7d2194b0560b76ef066d0aeb..001bcb064a1fd699c027f5872d217a3ee24737d3 100644 (file)
@@ -3,6 +3,7 @@
 namespace wcf\data\file;
 
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\system\file\processor\FileProcessor;
 
 /**
  * @author Alexander Ebert
@@ -16,4 +17,18 @@ use wcf\data\AbstractDatabaseObjectAction;
 class FileAction extends AbstractDatabaseObjectAction
 {
     protected $className = FileEditor::class;
+
+    #[\Override]
+    public function delete()
+    {
+        if ($this->objects === []) {
+            $this->readObjects();
+        }
+
+        if ($this->objects !== []) {
+            FileProcessor::getInstance()->delete($this->objects);
+        }
+
+        return parent::delete();
+    }
 }
index 7c90cbee12c2dcb7903ad059126e01d11cec6f3a..c4bd099d2e4b7d54fb1dceb7c006fd06ad5f6040 100644 (file)
@@ -4,6 +4,7 @@ namespace wcf\system\file\processor;
 
 use CuyZ\Valinor\Mapper\MappingError;
 use wcf\data\attachment\Attachment;
+use wcf\data\attachment\AttachmentAction;
 use wcf\data\attachment\AttachmentEditor;
 use wcf\data\file\File;
 use wcf\data\file\thumbnail\FileThumbnail;
@@ -186,6 +187,12 @@ final class AttachmentFileProcessor implements IFileProcessor
         ]);
     }
 
+    #[\Override]
+    public function delete(array $fileIDs, array $thumbnailIDs): void
+    {
+        (new AttachmentAction($fileIDs, 'delete'))->executeAction();
+    }
+
     private function getAttachmentHandlerFromContext(array $context): ?AttachmentHandler
     {
         try {
index 88141f1f4328c0c76389b10cb8d7f63042fbec49..bc5808fa106efdea2c0b112a1ca2573d37d03d06 100644 (file)
@@ -6,11 +6,13 @@ use wcf\data\file\File;
 use wcf\data\file\thumbnail\FileThumbnail;
 use wcf\data\file\thumbnail\FileThumbnailEditor;
 use wcf\data\file\thumbnail\FileThumbnailList;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\event\EventHandler;
 use wcf\system\file\processor\event\FileProcessorCollecting;
 use wcf\system\image\adapter\ImageAdapter;
 use wcf\system\image\ImageHandler;
 use wcf\system\SingletonFactory;
+use wcf\system\WCF;
 use wcf\util\FileUtil;
 use wcf\util\JSON;
 use wcf\util\StringUtil;
@@ -125,4 +127,23 @@ final class FileProcessor extends SingletonFactory
             $processor->adoptThumbnail($fileThumbnail);
         }
     }
+
+    public function delete(array $files): void
+    {
+        $fileIDs = \array_column($files, 'fileID');
+
+        $conditions = new PreparedStatementConditionBuilder();
+        $conditions->add('fileID IN (?)', [$fileIDs]);
+
+        $sql = "SELECT  thumbnailID
+                FROM    wcf1_file_thumbnail
+                {$conditions}";
+        $statement = WCF::getDB()->prepare($sql);
+        $statement->execute($conditions->getParameters());
+        $thumbnailIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+
+        foreach ($this->processors as $processor) {
+            $processor->delete($fileIDs, $thumbnailIDs);
+        }
+    }
 }
index 56d49368ab53919fdca6fc9d0014398c5b00c75b..4ea0128651acb1677da8391e0bc1918c6c0faf2e 100644 (file)
@@ -23,6 +23,12 @@ interface IFileProcessor
 
     public function canDownload(File $file): bool;
 
+    /**
+     * @param list<int> $files
+     * @param list<int> $thumbnails
+     */
+    public function delete(array $fileIDs, array $thumbnailIDs): void;
+
     public function getAllowedFileExtensions(array $context): array;
 
     public function getResizeConfiguration(): ResizeConfiguration;
index 47dd8cd1b8e0f6a311f312767e44b3fbb18118d7..fc26fb1bbc8147d5ed901dd8d41d63741e40499a 100644 (file)
@@ -108,8 +108,8 @@ class HtmlInputNodeImg extends AbstractHtmlInputNode
 
         $float = 'none';
         $thumbnail = false;
-
-        if (\strpos($element->getAttribute('src'), 'thumbnail=1') !== false) {
+        $src = $element->getAttribute('src');
+        if (\str_contains($src, 'thumbnail=1') || \str_ends_with($src, '.webp')) {
             $thumbnail = true;
         }