You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/migration/wsc60/php.md
+249Lines changed: 249 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -198,3 +198,252 @@ public class FooBarAction extends AbstractDatabaseObjectAction implements IMessa
198
198
}
199
199
}
200
200
```
201
+
202
+
## Migration to `FileProcessorFormField`
203
+
204
+
Previously, the `UploadFormField` class was used to create file upload fields in forms.
205
+
It is strongly recommended to use the new `FileProcessorFormField` instead which separates file validation and processing into a dedicated class, the `IFileProcessor`.
206
+
207
+
Only the fileID (or fileIDs) now need to be saved in the database.
208
+
These should reference `wcf1_file.fileID` through a foreign key.
209
+
210
+
The previously required function (`getFooUploadFiles`) to retrieve `UploadFile[]` is no longer needed and can be removed.
211
+
212
+
### Example
213
+
214
+
In this example, the `Foo` object will store the `imageID` of the uploaded file.
215
+
216
+
#### Example using `FileProcessorFormField`
217
+
218
+
The form field now provides information about which `IFileProcessor` should be used for the file upload, by specifying the object type for the definition `com.woltlab.wcf.file`.
219
+
220
+
```PHP
221
+
final class FooAddForm extends AbstractFormBuilderForm
222
+
{
223
+
#[\Override]
224
+
protected function createForm(): void
225
+
{
226
+
parent::createForm();
227
+
228
+
$this->form->appendChildren([
229
+
FormContainer::create('imageContainer')
230
+
->appendChildren([
231
+
FileProcessorFormField::create('imageID')
232
+
->singleFileUpload()
233
+
->required()
234
+
->objectType('foo.bar.image')
235
+
]),
236
+
]);
237
+
}
238
+
}
239
+
```
240
+
241
+
#### Example for implementing an `IFileProcessor`
242
+
243
+
The `objectID` in the `$context` comes from the form and corresponds to the objectID of the `FooAddForm::$formObject`.
244
+
245
+
This is a rather exhaustive example and tries to cover a lot of different use cases including but not limited to fine-grained control through user group permissions.
246
+
247
+
The `AbstractFileProcessor` implementation already provides a lot of sane defaults for less restricted uploads.
248
+
For example, if your field allows arbitrary files to be uploaded, you can skip that check in `acceptUpload()` and also remove the overriden method `getAllowedFileExtensions()` because the base implementation already permits all types of files.
249
+
250
+
Please see the explanation of the new [file uploads](../../php/api/file_uploads.md) to learn more.
251
+
252
+
```PHP
253
+
final class FooImageFileProcessor extends AbstractFileProcessor
254
+
{
255
+
#[\Override]
256
+
public function acceptUpload(string $filename, int $fileSize, array $context): FileProcessorPreflightResult
Copy file name to clipboardExpand all lines: docs/php/api/file_uploads.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,17 +6,17 @@ Attachments are implemented as an extra layer on top of the upload pipeline.
6
6
7
7
The most common use cases are the attachment system that relies on the WYSIWYG editor as well as the `FileProcessorFormField`.
8
8
9
-
# Provide the `IFileProcessor`
9
+
##Provide the `IFileProcessor`
10
10
11
11
At the very core of each uploadable type is an implementation of `IFileProcessor` that handles the validation and handling of new files.
12
12
13
13
It is strongly recommended to derive from `AbstractFileProcessor` that makes it easy to opt out of some extra features and will provide backwards compatibility with new features.
14
14
15
-
## Important Methods and Features
15
+
###Important Methods and Features
16
16
17
17
Please refer to the documentation in `IFileProcessor` for an explanation of methods that are not explained here.
18
18
19
-
### Thumbnails
19
+
####Thumbnails
20
20
21
21
It is possible to automatically generate thumbnails for any uploaded file.
22
22
The number of thumbnail variants is not limited but each thumbnail must have an identifier that is unique for your file processor.
@@ -50,7 +50,7 @@ The existing rebuild data worker for files will check the existing thumbnails ag
50
50
51
51
The identifier must be stable because it is used to verify if a specific thumbnail still matches the configured settings.
52
52
53
-
### Resizing Images Before Uploading
53
+
####Resizing Images Before Uploading
54
54
55
55
You can opt-in to the resize feature by returning a custom `ResizeConfiguration` from `getResizeConfiguration`, otherwise images of arbitrary size will be accepted.
56
56
@@ -75,22 +75,22 @@ public function getResizeConfiguration(): ResizeConfiguration
75
75
The `ResizeFileType` controls the output format of the resized image.
76
76
The available options are `jpeg` and `webp` but it is also possible to keep the existing image format.
77
77
78
-
### Adopting Files and Thumbnails
78
+
####Adopting Files and Thumbnails
79
79
80
80
Files are associated with your object type after being uploaded but you possibly want to store the file id in your database table.
81
81
This is where `adopt(File $file, array $context): void` comes into play which notifies you of the successful upload of a file while providing the context that is used to upload the file in the first place.
82
82
83
83
Thumbnails are generated in a separate request for performance reasons and you are being notified through `adoptThumbnail(FileThumbnail $thumbnail): void`.
84
84
This is meant to allow you to track the thumbnail id in the database.
85
85
86
-
### Tracking Downloads
86
+
####Tracking Downloads
87
87
88
88
File downloads are handled through the `FileDownloadAction` which validates the requested file and permissions to download it.
89
89
Every time a file is being downloaded, `trackDownload(File $file): void` is invoked to allow you to update any counters.
90
90
91
91
Static images are served directly by the web server for performance reasons and it is not possible to track those accesses.
92
92
93
-
## Registering the File Processor
93
+
###Registering the File Processor
94
94
95
95
The file processor is registered as an object type for `com.woltlab.wcf.file` through the `objectType.xml`:
96
96
@@ -109,11 +109,11 @@ The integration with the form builder enables you to focus on the file processin
109
109
110
110
Please see documentation for [FileProcessorFormField](form_fields.md#fileprocessorformfield) to learn more.
111
111
112
-
# Implementing an Unmanaged File Upload
112
+
##Implementing an Unmanaged File Upload
113
113
114
114
If you cannot use or want to use the existing form builder implementation you can still implement the UI yourself following this guide.
115
115
116
-
## Creating the Context for New Files
116
+
###Creating the Context for New Files
117
117
118
118
The HTML element for the file upload is generated through the helper method `FileProcessor::getHtmlElement()` that expects a reference to your `IFileProcessor` as well as a context for new files.
119
119
@@ -137,7 +137,7 @@ final class ExampleFileProcessor extends AbstractFileProcessor {
137
137
This code will generate a `<woltlab-core-file-upload>` HTML element that can be inserted anywhere on the page.
138
138
You do not need to initialize any extra JavaScript to make the element work, it will be initialized dynamically.
139
139
140
-
## Lifecycle of Uploaded Files
140
+
###Lifecycle of Uploaded Files
141
141
142
142
Any file that passes the pre-upload validation will be uploaded to the server.
143
143
This will trigger the `uploadStart` event on the `<woltlab-core-file-upload>` element, exposing a `<woltlab-core-file>` element as the only detail.
@@ -150,11 +150,11 @@ A successful upload will resolve the promise without any value, you can then acc
150
150
A failed upload will reject the `.ready` promise without any value, instead you can retrieve the error through the `.apiError` property if you want to further process it.
151
151
The UI is automatically updated with the error message, you only need to handle the `.apiError` property if you need to inspect the root cause.
152
152
153
-
## Deleting a File
153
+
###Deleting a File
154
154
155
155
You can delete a file from the UI by invoking `deleteFile()` from `WoltLabSuite/Core/Api/Files` which takes the value of `.fileId`.
156
156
157
-
## Render a Previously Uploaded File
157
+
###Render a Previously Uploaded File
158
158
159
159
You can render the `<woltlab-core-file>` element through `File::toHtmlElement()`.
160
160
This method accepts an optional list of meta data that is serialized to JSON and exposed on the `data-meta-data` property.
0 commit comments