Add support for copying files
authorAlexander Ebert <ebert@woltlab.com>
Fri, 7 Jun 2024 16:18:51 +0000 (18:18 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sat, 8 Jun 2024 10:20:25 +0000 (12:20 +0200)
wcfsetup/install/files/lib/data/attachment/AttachmentAction.class.php
wcfsetup/install/files/lib/system/file/processor/FileProcessor.class.php

index 743558448bc730e282293889e5f7b1973757e7be..9ab14d79cb55226b6d75b73d235576fdcb6aab62 100644 (file)
@@ -3,9 +3,11 @@
 namespace wcf\data\attachment;
 
 use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\file\thumbnail\FileThumbnailList;
 use wcf\data\object\type\ObjectTypeCache;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\UserInputException;
+use wcf\system\file\processor\FileProcessor;
 use wcf\system\WCF;
 
 /**
@@ -91,6 +93,30 @@ class AttachmentAction extends AbstractDatabaseObjectAction
 
         $newAttachmentIDs = [];
         foreach ($attachmentList as $attachment) {
+            $file = $attachment->getFile();
+            if ($file !== null) {
+                $file = FileProcessor::getInstance()->copy($file, 'com.woltlab.wcf.attachment');
+
+                $thumbnailID = $tinyThumbnailID = null;
+                if ($attachment->thumbnailID !== null || $attachment->tinyThumbnailID !== null) {
+                    $thumbnailList = new FileThumbnailList();
+                    $thumbnailList->getConditionBuilder()->add('fileID = ?', [$file->fileID]);
+                    $thumbnailList->readObjects();
+
+                    foreach ($thumbnailList as $thumbnail) {
+                        switch ($thumbnail->identifier) {
+                            case '':
+                                $thumbnailID = $thumbnail->thumbnailID;
+                                break;
+
+                            case 'tiny':
+                                $tinyThumbnailID = $thumbnail->thumbnailID;
+                                break;
+                        }
+                    }
+                }
+            }
+
             $newAttachment = AttachmentEditor::create([
                 'objectTypeID' => $targetObjectType->objectTypeID,
                 'objectID' => $this->parameters['targetObjectID'],
@@ -114,18 +140,11 @@ class AttachmentAction extends AbstractDatabaseObjectAction
                 'lastDownloadTime' => $attachment->lastDownloadTime,
                 'uploadTime' => $attachment->uploadTime,
                 'showOrder' => $attachment->showOrder,
+                'fileID' => $file?->fileID,
+                'thumbnailID' => $thumbnailID,
+                'tinyThumbnailID' => $tinyThumbnailID,
             ]);
 
-            // copy attachment
-            @\copy($attachment->getLocation(), $newAttachment->getLocation());
-
-            if ($attachment->tinyThumbnailSize) {
-                @\copy($attachment->getTinyThumbnailLocation(), $newAttachment->getTinyThumbnailLocation());
-            }
-            if ($attachment->thumbnailSize) {
-                @\copy($attachment->getThumbnailLocation(), $newAttachment->getThumbnailLocation());
-            }
-
             $newAttachmentIDs[$attachment->attachmentID] = $newAttachment->attachmentID;
         }
 
index 855cacf33abf6bdc84fd1ecdf16c3f5a45f94dc2..0255fb5ab6c903266954c9cdc9c72550fec3a60e 100644 (file)
@@ -284,4 +284,59 @@ final class FileProcessor extends SingletonFactory
 
         return $maximumFileSize;
     }
+
+    public function copy(File $oldFile, string $objectType): File
+    {
+        $objectTypeObj = $this->getObjectType($objectType);
+        if ($objectTypeObj === null) {
+            throw new \InvalidArgumentException("The object type '{$objectType}' is invalid.");
+        }
+
+        $newFile = FileEditor::create([
+            'filename' => $oldFile->filename,
+            'fileSize' => $oldFile->fileSize,
+            'fileHash' => $oldFile->fileHash,
+            'fileExtension' => $oldFile->fileExtension,
+            'secret' => \hex2bin(\random_bytes(10)),
+            'objectTypeID' => $objectTypeObj->objectTypeID,
+            'mimeType' => $oldFile->mimeType,
+            'width' => $oldFile->width,
+            'height' => $oldFile->height,
+            'fileHashWebp' => $oldFile->fileHashWebp,
+        ]);
+
+        \copy($oldFile->getPathname(), $newFile->getPathname());
+
+        if ($oldFile->fileHashWebp !== null) {
+            \copy($oldFile->getPathnameWebp(), $newFile->getPathnameWebp());
+        }
+
+        $this->copyThumbnails($oldFile->fileID, $newFile->fileID);
+
+        return $newFile;
+    }
+
+    private function copyThumbnails(int $oldFileID, int $newFileID): void
+    {
+        $thumbnailList = new FileThumbnailList();
+        $thumbnailList->getConditionBuilder()->add("fileID = ?", [$oldFileID]);
+        $thumbnailList->readObjects();
+
+        foreach ($thumbnailList as $oldThumbnail) {
+            $newThumbnail = FileThumbnailEditor::create([
+                'fileID' => $newFileID,
+                'identifier' => $oldThumbnail->identifier,
+                'fileHash' => $oldThumbnail->fileHash,
+                'fileExtension' => $oldThumbnail->fileExtension,
+                'width' => $oldThumbnail->width,
+                'height' => $oldThumbnail->height,
+                'formatChecksum' => $oldThumbnail->formatChecksum,
+            ]);
+
+            \copy(
+                $oldThumbnail->getPath() . $oldThumbnail->getSourceFilename(),
+                $newThumbnail->getPath() . $newThumbnail->getSourceFilename(),
+            );
+        }
+    }
 }