Skip to content

Commit e3cf697

Browse files
Cyperghostdtdesign
andauthored
Implement a command to copy attachments (#6419)
* Implement a command to copy attachments * Update wcfsetup/install/files/lib/command/attachment/CopyAttachments.class.php Co-authored-by: Alexander Ebert <[email protected]> --------- Co-authored-by: Alexander Ebert <[email protected]>
1 parent 6fab4b3 commit e3cf697

File tree

2 files changed

+131
-74
lines changed

2 files changed

+131
-74
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?php
2+
3+
namespace wcf\command\attachment;
4+
5+
use wcf\data\attachment\Attachment;
6+
use wcf\data\attachment\AttachmentEditor;
7+
use wcf\data\attachment\AttachmentList;
8+
use wcf\data\file\thumbnail\FileThumbnailList;
9+
use wcf\data\object\type\ObjectType;
10+
use wcf\data\object\type\ObjectTypeCache;
11+
use wcf\system\file\processor\FileProcessor;
12+
13+
/**
14+
* Copies attachments from one object to another.
15+
* Returns an array of old attachmentIDs as keys and new attachmentIDs as values.
16+
*
17+
* @author Olaf Braun
18+
* @copyright 2001-2025 WoltLab GmbH
19+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
20+
* @since 6.3
21+
*/
22+
final class CopyAttachments
23+
{
24+
public function __construct(
25+
private readonly string $sourceObjectType,
26+
private readonly int $sourceObjectID,
27+
private readonly string $targetObjectType,
28+
private readonly int $targetObjectID,
29+
) {
30+
}
31+
32+
/**
33+
* @return array<int, int>
34+
*/
35+
public function __invoke(): array
36+
{
37+
$sourceObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
38+
'com.woltlab.wcf.attachment.objectType',
39+
$this->sourceObjectType
40+
);
41+
$targetObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
42+
'com.woltlab.wcf.attachment.objectType',
43+
$this->targetObjectType
44+
);
45+
46+
$attachments = $this->getAttachments($sourceObjectType, $this->sourceObjectID);
47+
48+
$newAttachmentIDs = [];
49+
foreach ($attachments as $attachment) {
50+
$newAttachment = $this->copyAttachment($targetObjectType, $attachment);
51+
52+
$newAttachmentIDs[$attachment->attachmentID] = $newAttachment->attachmentID;
53+
}
54+
55+
return $newAttachmentIDs;
56+
}
57+
58+
/**
59+
* @return Attachment[]
60+
*/
61+
private function getAttachments(ObjectType $sourceObjectType, int $sourceObjectID): array
62+
{
63+
$attachmentList = new AttachmentList();
64+
$attachmentList->getConditionBuilder()->add("attachment.objectTypeID = ?", [$sourceObjectType->objectTypeID]);
65+
$attachmentList->getConditionBuilder()->add("attachment.objectID = ?", [$sourceObjectID]);
66+
$attachmentList->readObjects();
67+
68+
return $attachmentList->getObjects();
69+
}
70+
71+
private function copyAttachment(ObjectType $targetObjectType, Attachment $oldAttachment): Attachment
72+
{
73+
$file = $oldAttachment->getFile();
74+
$thumbnailID = null;
75+
$tinyThumbnailID = null;
76+
77+
if ($file !== null) {
78+
$file = FileProcessor::getInstance()->copy($file, 'com.woltlab.wcf.attachment');
79+
80+
if ($oldAttachment->thumbnailID !== null || $oldAttachment->tinyThumbnailID !== null) {
81+
$thumbnailList = new FileThumbnailList();
82+
$thumbnailList->getConditionBuilder()->add('fileID = ?', [$file->fileID]);
83+
$thumbnailList->readObjects();
84+
85+
foreach ($thumbnailList->getObjects() as $thumbnail) {
86+
match ($thumbnail->identifier) {
87+
'' => $thumbnailID = $thumbnail->thumbnailID,
88+
'tiny' => $tinyThumbnailID = $thumbnail->thumbnailID,
89+
};
90+
}
91+
}
92+
}
93+
94+
return AttachmentEditor::create([
95+
'objectTypeID' => $targetObjectType->objectTypeID,
96+
'objectID' => $this->targetObjectID,
97+
'userID' => $oldAttachment->userID,
98+
'filename' => $oldAttachment->filename,
99+
'filesize' => $oldAttachment->filesize,
100+
'fileType' => $oldAttachment->fileType,
101+
'fileHash' => $oldAttachment->fileHash,
102+
'isImage' => $oldAttachment->isImage,
103+
'width' => $oldAttachment->width,
104+
'height' => $oldAttachment->height,
105+
'tinyThumbnailType' => $oldAttachment->tinyThumbnailType,
106+
'tinyThumbnailSize' => $oldAttachment->tinyThumbnailSize,
107+
'tinyThumbnailWidth' => $oldAttachment->tinyThumbnailWidth,
108+
'tinyThumbnailHeight' => $oldAttachment->tinyThumbnailHeight,
109+
'thumbnailType' => $oldAttachment->thumbnailType,
110+
'thumbnailSize' => $oldAttachment->thumbnailSize,
111+
'thumbnailWidth' => $oldAttachment->thumbnailWidth,
112+
'thumbnailHeight' => $oldAttachment->thumbnailHeight,
113+
'downloads' => $oldAttachment->downloads,
114+
'lastDownloadTime' => $oldAttachment->lastDownloadTime,
115+
'uploadTime' => $oldAttachment->uploadTime,
116+
'showOrder' => $oldAttachment->showOrder,
117+
'fileID' => $file?->fileID,
118+
'thumbnailID' => $thumbnailID,
119+
'tinyThumbnailID' => $tinyThumbnailID,
120+
]);
121+
}
122+
}

wcfsetup/install/files/lib/data/attachment/AttachmentAction.class.php

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
namespace wcf\data\attachment;
44

5+
use wcf\command\attachment\CopyAttachments;
56
use wcf\data\AbstractDatabaseObjectAction;
6-
use wcf\data\file\thumbnail\FileThumbnailList;
77
use wcf\data\object\type\ObjectTypeCache;
88
use wcf\system\exception\PermissionDeniedException;
99
use wcf\system\exception\UserInputException;
10-
use wcf\system\file\processor\FileProcessor;
1110
use wcf\system\WCF;
1211

1312
/**
@@ -75,82 +74,18 @@ public function generateThumbnails()
7574
* Copies attachments from one object id to another.
7675
*
7776
* @return array{attachmentIDs: array<int, int>}
77+
*
78+
* @deprecated 6.3 use `CopyAttachments` instead.
7879
*/
7980
public function copy()
8081
{
81-
$sourceObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
82-
'com.woltlab.wcf.attachment.objectType',
83-
$this->parameters['sourceObjectType']
84-
);
85-
$targetObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName(
86-
'com.woltlab.wcf.attachment.objectType',
87-
$this->parameters['targetObjectType']
88-
);
89-
90-
$attachmentList = new AttachmentList();
91-
$attachmentList->getConditionBuilder()->add("attachment.objectTypeID = ?", [$sourceObjectType->objectTypeID]);
92-
$attachmentList->getConditionBuilder()->add("attachment.objectID = ?", [$this->parameters['sourceObjectID']]);
93-
$attachmentList->readObjects();
94-
95-
$newAttachmentIDs = [];
96-
foreach ($attachmentList as $attachment) {
97-
$file = $attachment->getFile();
98-
if ($file !== null) {
99-
$file = FileProcessor::getInstance()->copy($file, 'com.woltlab.wcf.attachment');
100-
101-
$thumbnailID = $tinyThumbnailID = null;
102-
if ($attachment->thumbnailID !== null || $attachment->tinyThumbnailID !== null) {
103-
$thumbnailList = new FileThumbnailList();
104-
$thumbnailList->getConditionBuilder()->add('fileID = ?', [$file->fileID]);
105-
$thumbnailList->readObjects();
106-
107-
foreach ($thumbnailList as $thumbnail) {
108-
switch ($thumbnail->identifier) {
109-
case '':
110-
$thumbnailID = $thumbnail->thumbnailID;
111-
break;
112-
113-
case 'tiny':
114-
$tinyThumbnailID = $thumbnail->thumbnailID;
115-
break;
116-
}
117-
}
118-
}
119-
}
120-
121-
$newAttachment = AttachmentEditor::create([
122-
'objectTypeID' => $targetObjectType->objectTypeID,
123-
'objectID' => $this->parameters['targetObjectID'],
124-
'userID' => $attachment->userID,
125-
'filename' => $attachment->filename,
126-
'filesize' => $attachment->filesize,
127-
'fileType' => $attachment->fileType,
128-
'fileHash' => $attachment->fileHash,
129-
'isImage' => $attachment->isImage,
130-
'width' => $attachment->width,
131-
'height' => $attachment->height,
132-
'tinyThumbnailType' => $attachment->tinyThumbnailType,
133-
'tinyThumbnailSize' => $attachment->tinyThumbnailSize,
134-
'tinyThumbnailWidth' => $attachment->tinyThumbnailWidth,
135-
'tinyThumbnailHeight' => $attachment->tinyThumbnailHeight,
136-
'thumbnailType' => $attachment->thumbnailType,
137-
'thumbnailSize' => $attachment->thumbnailSize,
138-
'thumbnailWidth' => $attachment->thumbnailWidth,
139-
'thumbnailHeight' => $attachment->thumbnailHeight,
140-
'downloads' => $attachment->downloads,
141-
'lastDownloadTime' => $attachment->lastDownloadTime,
142-
'uploadTime' => $attachment->uploadTime,
143-
'showOrder' => $attachment->showOrder,
144-
'fileID' => $file?->fileID,
145-
'thumbnailID' => $thumbnailID ?? null,
146-
'tinyThumbnailID' => $tinyThumbnailID ?? null,
147-
]);
148-
149-
$newAttachmentIDs[$attachment->attachmentID] = $newAttachment->attachmentID;
150-
}
151-
15282
return [
153-
'attachmentIDs' => $newAttachmentIDs,
83+
'attachmentIDs' => (new CopyAttachments(
84+
$this->parameters['sourceObjectType'],
85+
$this->parameters['sourceObjectID'],
86+
$this->parameters['targetObjectType'],
87+
$this->parameters['targetObjectID']
88+
))()
15489
];
15590
}
15691
}

0 commit comments

Comments
 (0)