--- /dev/null
+{unsafe:$fileProcessorHtmlElement}
+
+<script data-relocate="true">
+ require(["WoltLabSuite/Core/Form/Builder/Field/Controller/FileProcessor"], ({ FileProcessor }) => {
+ new FileProcessor(
+ '{@$field->getPrefixedId()|encodeJS}',
+ [],
+ );
+ });
+</script>
--- /dev/null
+/**
+ * @author Olaf Braun
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+
+import WoltlabCoreFileElement from "WoltLabSuite/Core/Component/File/woltlab-core-file";
+import DomUtil from "WoltLabSuite/Core/Dom/Util";
+
+export class FileProcessor {
+ readonly #container: HTMLElement;
+ readonly #uploadButton: WoltlabCoreFileUploadElement;
+ readonly #files = new Map<number, WoltlabCoreFileElement>();
+ readonly #fieldId: string;
+
+ constructor(fieldId: string, values: string[]) {
+ this.#fieldId = fieldId;
+
+ this.#container = document.getElementById(fieldId + "Container")!;
+ if (this.#container === null) {
+ throw new Error("Unknown field with id '" + fieldId + "'");
+ }
+
+ values.forEach((html) => {
+ const element = document.createElement("template");
+ DomUtil.setInnerHtml(element, html);
+
+ void this.#registerFile(element.content.querySelector<WoltlabCoreFileElement>("woltlab-core-file")!);
+ });
+
+ this.#uploadButton = this.#container.querySelector("woltlab-core-file-upload") as WoltlabCoreFileUploadElement;
+ this.#uploadButton.addEventListener("uploadStart", (event: CustomEvent<WoltlabCoreFileElement>) => {
+ void this.#registerFile(event.detail);
+ });
+ }
+
+ async #registerFile(element: WoltlabCoreFileElement): Promise<void> {
+ this.#uploadButton.insertAdjacentElement("beforebegin", element);
+
+ await element.ready;
+ this.#files.set(element.fileId!, element);
+ const input = document.createElement("input");
+ input.type = "hidden";
+ input.name = this.#fieldId + (this.#uploadButton.maximumCount === 1 ? "" : "[]");
+ input.value = element.fileId!.toString();
+ element.insertAdjacentElement("afterend", input);
+
+ if (this.#uploadButton.maximumCount === 1) {
+ // single file upload
+ element.dataset.previewUrl = element.link!;
+ element.unbounded = true;
+ }
+ }
+}
--- /dev/null
+/**
+ * @author Olaf Braun
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since 6.1
+ */
+define(["require", "exports", "tslib", "WoltLabSuite/Core/Dom/Util"], function (require, exports, tslib_1, Util_1) {
+ "use strict";
+ Object.defineProperty(exports, "__esModule", { value: true });
+ exports.FileProcessor = void 0;
+ Util_1 = tslib_1.__importDefault(Util_1);
+ class FileProcessor {
+ #container;
+ #uploadButton;
+ #files = new Map();
+ #fieldId;
+ constructor(fieldId, values) {
+ this.#fieldId = fieldId;
+ this.#container = document.getElementById(fieldId + "Container");
+ if (this.#container === null) {
+ throw new Error("Unknown field with id '" + fieldId + "'");
+ }
+ values.forEach((html) => {
+ const element = document.createElement("template");
+ Util_1.default.setInnerHtml(element, html);
+ void this.#registerFile(element.content.querySelector("woltlab-core-file"));
+ });
+ this.#uploadButton = this.#container.querySelector("woltlab-core-file-upload");
+ this.#uploadButton.addEventListener("uploadStart", (event) => {
+ void this.#registerFile(event.detail);
+ });
+ }
+ async #registerFile(element) {
+ this.#uploadButton.insertAdjacentElement("beforebegin", element);
+ await element.ready;
+ this.#files.set(element.fileId, element);
+ const input = document.createElement("input");
+ input.type = "hidden";
+ input.name = this.#fieldId + (this.#uploadButton.maximumCount === 1 ? "" : "[]");
+ input.value = element.fileId.toString();
+ element.insertAdjacentElement("afterend", input);
+ if (this.#uploadButton.maximumCount === 1) {
+ // single file upload
+ element.dataset.previewUrl = element.link;
+ element.unbounded = true;
+ }
+ }
+ }
+ exports.FileProcessor = FileProcessor;
+});
--- /dev/null
+<?php
+
+namespace wcf\system\form\builder\field;
+
+use wcf\system\file\processor\FileProcessor;
+use wcf\system\file\processor\IFileProcessor;
+use wcf\system\form\builder\TObjectTypeFormNode;
+
+/**
+ * Form field for file processors.
+ *
+ * @author Olaf Braun
+ * @copyright 2001-2024 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ */
+final class FileProcessorFormField extends AbstractFormField
+{
+ use TObjectTypeFormNode;
+
+ /**
+ * @inheritDoc
+ */
+ protected $templateName = 'shared_fileProcessorFormField';
+
+ private array $context = [];
+
+ #[\Override]
+ public function readValue()
+ {
+ \wcfDebug($this->getDocument()->getRequestData());
+ if ($this->getDocument()->hasRequestData($this->getPrefixedId())) {
+ $this->context = $this->getDocument()->getRequestData($this->getPrefixedId());
+ }
+ }
+
+ #[\Override]
+ public function getHtmlVariables()
+ {
+ return [
+ 'fileProcessorHtmlElement' => FileProcessor::getInstance()->getHtmlElement(
+ $this->getFileProcessor(),
+ $this->context
+ ),
+ 'maxUploads' => $this->getFileProcessor()->getMaximumCount($this->context),
+ ];
+ }
+
+ public function getFileProcessor(): IFileProcessor
+ {
+ return $this->getObjectType()->getProcessor();
+ }
+
+ #[\Override]
+ public function getObjectTypeDefinition()
+ {
+ return 'com.woltlab.wcf.file';
+ }
+
+ /**
+ * Returns the context for the file processor.
+ */
+ public function getContext(): array
+ {
+ return $this->context;
+ }
+
+ /**
+ * Sets the context for the file processor.
+ */
+ public function context(array $context): self
+ {
+ $this->context = $context;
+
+ return $this;
+ }
+}