use wcf\data\file\temporary\FileTemporary;
use wcf\data\file\thumbnail\FileThumbnailEditor;
use wcf\data\file\thumbnail\FileThumbnailList;
+use wcf\system\file\processor\FileProcessor;
use wcf\util\FileUtil;
/**
return $file;
}
+
+ public static function createFromExistingFile(
+ string $pathname,
+ string $originalFilename,
+ string $objectTypeName
+ ): ?File {
+ if (!\is_readable($pathname)) {
+ return null;
+ }
+
+ $objectType = FileProcessor::getInstance()->getObjectType($objectTypeName);
+ if ($objectType === null) {
+ return new \RuntimeException("The object type '{$objectTypeName}' is not valid.");
+ }
+
+ $mimeType = FileUtil::getMimeType($pathname);
+ $isImage = match ($mimeType) {
+ 'image/gif' => true,
+ 'image/jpeg' => true,
+ 'image/png' => true,
+ 'image/webp' => true,
+ default => false,
+ };
+
+ $width = $height = null;
+ if ($isImage) {
+ [$width, $height] = \getimagesize($pathname);
+ }
+
+ $fileAction = new FileAction([], 'create', ['data' => [
+ 'filename' => $originalFilename,
+ 'fileSize' => \filesize($pathname),
+ 'fileHash' => \hash_file('sha256', $pathname),
+ 'fileExtension' => File::getSafeFileExtension($mimeType, $originalFilename),
+ 'secret' => \bin2hex(\random_bytes(16)),
+ 'objectTypeID' => $objectType->objectTypeID,
+ 'mimeType' => $mimeType,
+ 'width' => $width,
+ 'height' => $height,
+ ]]);
+ $file = $fileAction->executeAction()['returnValues'];
+ \assert($file instanceof File);
+
+ $filePath = $file->getPath();
+ if (!\is_dir($filePath)) {
+ \mkdir($filePath, recursive: true);
+ }
+
+ \rename(
+ $pathname,
+ $filePath . $file->getSourceFilename()
+ );
+
+ return $file;
+ }
}
namespace wcf\system\worker;
-use wcf\data\attachment\AttachmentAction;
+use wcf\data\attachment\Attachment;
+use wcf\data\attachment\AttachmentEditor;
use wcf\data\attachment\AttachmentList;
+use wcf\data\file\FileEditor;
+use wcf\system\database\exception\DatabaseQueryException;
use wcf\system\exception\SystemException;
+use wcf\system\database\exception\DatabaseQueryExecutionException;
+use wcf\system\database\exception\DatabaseTransactionException;
+use wcf\system\WCF;
/**
* Worker implementation for updating attachments.
*
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
+ * @author Marcel Werk
+ * @copyright 2001-2024 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*
* @method AttachmentList getObjectList()
+ * @deprecated 6.1 Should be removed in 6.2 as its only purpose is to migrate to the new upload API.
*/
-class AttachmentRebuildDataWorker extends AbstractRebuildDataWorker
+class AttachmentRebuildDataWorker extends AbstractLinearRebuildDataWorker
{
/**
* @inheritDoc
/**
* @inheritDoc
*/
- protected $limit = 10;
+ protected $limit = 100;
+
+ #[\Override]
+ public function execute()
+ {
+ parent::execute();
+
+ /** @var array<int,int> */
+ $attachmentToFileID = [];
+
+ /** @var list<int> */
+ $defunctAttachmentIDs = [];
+
+ foreach ($this->objectList as $attachment) {
+ \assert($attachment instanceof Attachment);
+
+ if ($attachment->fileID !== null) {
+ continue;
+ }
+
+ $attachment->migrateStorage();
+
+ $file = FileEditor::createFromExistingFile(
+ $attachment->getLocation(),
+ $attachment->filename,
+ 'com.woltlab.wcf.attachment'
+ );
+
+ if ($file === null) {
+ $defunctAttachmentIDs[] = $attachment->attachmentID;
+ continue;
+ }
+
+ $attachmentToFileID[$attachment->attachmentID] = $file->fileID;
+ }
+
+ $this->setFileIDs($attachmentToFileID);
+ $this->removeDefunctAttachments($defunctAttachmentIDs);
+ }
/**
- * @inheritDoc
+ * @param array<int,int> $attachmentToFileID
*/
- protected function initObjectList()
+ private function setFileIDs(array $attachmentToFileID): void
{
- parent::initObjectList();
+ if ($attachmentToFileID === []) {
+ return;
+ }
+
+ $sql = "UPDATE wcf1_attachment
+ SET fileID = ?
+ WHERE attachmentID = ?";
+ $statement = WCF::getDB()->prepare($sql);
- $this->objectList->sqlOrderBy = 'attachment.attachmentID';
+ WCF::getDB()->beginTransaction();
+ foreach ($attachmentToFileID as $attachmentID => $fileID) {
+ $statement->execute([
+ $fileID,
+ $attachmentID,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
}
/**
- * @inheritDoc
+ * @param list<int> $attachmentIDs
*/
- public function execute()
+ private function removeDefunctAttachments(array $attachmentIDs): void
{
- parent::execute();
-
- /** @var \wcf\data\attachment\Attachment $attachment */
- foreach ($this->objectList as $attachment) {
- $attachment->migrateStorage();
- try {
- $action = new AttachmentAction([$attachment], 'generateThumbnails');
- $action->executeAction();
- } catch (SystemException $e) {
- }
+ if ($attachmentIDs === []) {
+ return;
}
+
+ AttachmentEditor::deleteAll($attachmentIDs);
}
}