Skip to content

Commit 23515bc

Browse files
committed
Insert basic information to migrate to FileProcessorFormField
1 parent 610e7cb commit 23515bc

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

docs/migration/wsc60/php.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,184 @@ public class FooBarAction extends AbstractDatabaseObjectAction implements IMessa
198198
}
199199
}
200200
```
201+
202+
## Migration to `FileProcessorFormField`
203+
204+
Previously, the `UploadFormField` class was used to create file upload fields in forms.
205+
Now, the new `FileProcessorFormField` should be used,
206+
which separates file validation and processing into a dedicated class, the `IFileProcessor`.
207+
208+
#### Example using `FileProcessorFormField`
209+
210+
With the new `FileProcessorFormField`, file validation and processing is handled by a separate class,
211+
the `IFileProcessor`.
212+
The form field now provides information about which `IFileProcessor` should be used for the file upload,
213+
by specifying the object type of `com.woltlab.wcf.file`.
214+
215+
```PHP
216+
#[\Override]
217+
protected function createForm(): void
218+
{
219+
parent::createForm();
220+
$this->form->appendChildren([
221+
FormContainer::create('imageContainer')
222+
->appendChildren([
223+
FileProcessorFormField::create('imageID')
224+
->singleFileUpload()
225+
->required()
226+
->context($this->getContent())
227+
->objectType('foo.bar.image')
228+
]),
229+
]);
230+
}
231+
232+
protected function getContent(): array
233+
{
234+
if ($this->formObject !== null) {
235+
return [
236+
'fooID' => $this->formObject->fooID,
237+
];
238+
}
239+
return [];
240+
}
241+
```
242+
243+
#### Example for implementing an `IFileProcessor`
244+
245+
```PHP
246+
final class FooImageFileProcessor extends AbstractFileProcessor
247+
{
248+
#[\Override]
249+
public function acceptUpload(string $filename, int $fileSize, array $context): FileProcessorPreflightResult
250+
{
251+
if (isset($context['fooID'])) {
252+
$foo = $this->getFoo($context);
253+
if ($foo === null) {
254+
return FileProcessorPreflightResult::InvalidContext;
255+
}
256+
257+
if (!$foo->canEdit()) {
258+
return FileProcessorPreflightResult::InsufficientPermissions;
259+
}
260+
} elseif (!WCF::getSession()->getPermission('foo.bar.canAdd')) {
261+
return FileProcessorPreflightResult::InsufficientPermissions;
262+
}
263+
264+
if ($fileSize > $this->getMaximumSize($context)) {
265+
return FileProcessorPreflightResult::FileSizeTooLarge;
266+
}
267+
268+
if (!FileUtil::endsWithAllowedExtension($filename, $this->getAllowedFileExtensions($context))) {
269+
return FileProcessorPreflightResult::FileExtensionNotPermitted;
270+
}
271+
272+
return FileProcessorPreflightResult::Passed;
273+
}
274+
275+
#[\Override]
276+
public function getMaximumSize(array $context): ?int
277+
{
278+
return WCF::getSession()->getPermission('foo.bar.image.maxSize');
279+
}
280+
281+
#[\Override]
282+
public function getAllowedFileExtensions(array $context): array
283+
{
284+
return \explode("\n", WCF::getSession()->getPermission('foo.bar.image.allowedFileExtensions'));
285+
}
286+
287+
#[\Override]
288+
public function canAdopt(File $file, array $context): bool
289+
{
290+
$fooFromContext = $this->getFoo($context);
291+
$fooFromCoreFile = $this->getFooByFile($file);
292+
293+
if ($fooFromCoreFile === null) {
294+
return true;
295+
}
296+
297+
if ($fooFromCoreFile->fooID === $fooFromContext->fooID) {
298+
return true;
299+
}
300+
301+
return false;
302+
}
303+
304+
#[\Override]
305+
public function adopt(File $file, array $context): void
306+
{
307+
$foo = $this->getFoo($context);
308+
if ($foo === null) {
309+
return;
310+
}
311+
312+
(new FooEditor($foo))->update([
313+
'imageID' => $file->fileID,
314+
]);
315+
}
316+
317+
#[\Override]
318+
public function canDelete(File $file): bool
319+
{
320+
$foo = $this->getFooByFile($file);
321+
if ($foo === null) {
322+
return WCF::getSession()->getPermission('foo.bar.canAdd');
323+
}
324+
325+
return false;
326+
}
327+
328+
#[\Override]
329+
public function canDownload(File $file): bool
330+
{
331+
$foo = $this->getFooByFile($file);
332+
if ($foo === null) {
333+
return WCF::getSession()->getPermission('foo.bar.canAdd');
334+
}
335+
336+
return $foo->canRead();
337+
}
338+
339+
#[\Override]
340+
public function delete(array $fileIDs, array $thumbnailIDs): void
341+
{
342+
$fooList = new FooList();
343+
$fooList->getConditionBuilder()->add('imageID IN (?)', [$fileIDs]);
344+
$fooList->readObjects();
345+
346+
if ($fooList->count() === 0) {
347+
return;
348+
}
349+
350+
(new FooAction($fooList->getObjects(), 'delete'))->executeAction();
351+
}
352+
353+
#[\Override]
354+
public function getObjectTypeName(): string
355+
{
356+
return 'foo.bar.image';
357+
}
358+
359+
#[\Override]
360+
public function countExistingFiles(array $context): ?int
361+
{
362+
$foo = $this->getFoo($context);
363+
if ($foo === null) {
364+
return null;
365+
}
366+
367+
return $foo->imageID === null ? 0 : 1;
368+
}
369+
370+
private function getFoo(array $context): ?Foo
371+
{
372+
// extract foo from context
373+
}
374+
375+
private function getFooByFile(File $file): ?Foo
376+
{
377+
// search foo in database by given file
378+
}
379+
}
380+
```
381+

0 commit comments

Comments
 (0)