<commit_before><?php

namespace wcf\system\form\builder\field;

use wcf\data\IStorableObject;
use wcf\system\file\upload\UploadField;
use wcf\system\file\upload\UploadFile;
use wcf\system\file\upload\UploadHandler;
use wcf\system\form\builder\data\processor\CustomFormDataProcessor;
use wcf\system\form\builder\field\validation\FormFieldValidationError;
use wcf\system\form\builder\IFormDocument;
use wcf\util\ImageUtil;

/**
 * Implementation of a form field for to uploads.
 *
 * @author  <NAME>
 * @copyright   2001-2019 WoltLab GmbH
 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package WoltLabSuite\Core\System\Form\Builder\Field
 * @since   5.2
 */
class UploadFormField extends AbstractFormField
{
    use TMaximumFormField {
        maximum as traitMaximum;
    }
    use TMinimumFormField;

    /**
     * @inheritDoc
     */
    protected $javaScriptDataHandlerModule = 'WoltLabSuite/Core/Form/Builder/Field/Value';

    /**
     * This flag indicates whether only images can uploaded via this field.
     * <strong>Attention</strong>: SVG images can contain bad code, therefore do not
     * use this option, outside the acp or check the file whether remote code is contained.
     * @var bool
     */
    protected $imageOnly = false;

    /**
     * This flag indicates whether SVG images are treated as image in the image only mode.
     * @var bool
     */
    protected $allowSvgImage = false;

    /**
     * Acceptable file types.
     * @var null|string[]
     * @since 5.3
     */
    protected $acceptableFiles;

    /**
     * maximum filesize for each uploaded file
     * @var null|number
     */
    protected $maximumFilesize;

    /**
     * minimum image width for each uploaded file
     * @var null|number
     */
    protected $minimumImageWidth;

    /**
     * maximum image width for each uploaded file
     * @var null|number
     */
    protected $maximumImageWidth;

    /**
     * minimum image height for each uploaded file
     * @var null|number
     */
    protected $minimumImageHeight;

    /**
     * maximum image height for each uploaded file
     * @var null|number
     */
    protected $maximumImageHeight;

    /**
     * @inheritDoc
     */
    protected $templateName = '__uploadFormField';

    /**
     * Array of temporary values, which are assigned, after the method `populate` are called.
     * @var array
     */
    private $values = [];

    /**
     * Flag whether the field is already unregistered.
     * @var bool
     */
    private $cleaned = false;

    /**
     * Unregisters the current field in the upload handler.
     */
    private function unregisterField()
    {
        if (UploadHandler::getInstance()->isRegisteredFieldId($this->getPrefixedId())) {
            UploadHandler::getInstance()->unregisterUploadField($this->getPrefixedId());
        }
    }

    /**
     * Builds the UploadField class.
     *
     * @return      UploadField
     */
    protected function buildUploadField()
    {
        $uploadField = new UploadField($this->getPrefixedId());
        $uploadField->maxFiles = $this->getMaximum();
        $uploadField->setImageOnly($this->isImageOnly());
        if ($this->isImageOnly()) {
            $uploadField->setAllowSvgImage($this->svgImageAllowed());
        }
        $uploadField->setAcceptableFiles($this->getAcceptableFiles());

        return $uploadField;
    }

    /**
     * Returns true, iff the current field is already registered.
     *
     * @return bool
     */
    private function isRegistered()
    {
        return $this->isPopulated;
    }

    /**
     * @inheritDoc
     * @return      UploadFile[]
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getValue()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        return UploadHandler::getInstance()->getFilesByFieldId($this->getPrefixedId());
    }

    /**
     * Returns the removed files for the field.
     *
     * @param bool $processFiles
     * @return      UploadFile[]
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getRemovedFiles($processFiles = false)
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling the method.");
        }

        return UploadHandler::getInstance()->getRemovedFiledByFieldId($this->getPrefixedId(), $processFiles);
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function readValue()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function validate()
    {
        parent::validate();

        if (empty($this->getValue())) {
            if ($this->isRequired()) {
                $this->addValidationError(new FormFieldValidationError('empty'));
            }
        }

        if ($this->getMinimum() !== null && \count($this->getValue()) < $this->getMinimum()) {
            $this->addValidationError(new FormFieldValidationError(
                'minimum',
                'wcf.form.field.upload.error.minimum',
                ['minimum' => $this->getMinimum()]
            ));
        } elseif ($this->getMaximum() !== null && \count($this->getValue()) > $this->getMaximum()) {
            $this->addValidationError(new FormFieldValidationError(
                'maximum',
                'wcf.form.field.upload.error.maximum',
                ['maximum' => $this->getMaximum()]
            ));
        }

        if ($this->getMaximumFilesize() !== null) {
            foreach ($this->getValue() as $file) {
                $filesize = \filesize($file->getLocation());
                if ($filesize > $this->getMaximumFilesize()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumFilesize',
                        'wcf.form.field.upload.error.maximumFilesize',
                        [
                            'maximumFilesize' => $this->getMaximumFilesize(),
                            'file' => $file,
                        ]
                    ));
                }
            }
        }

        if (
            $this->getMinimumImageWidth() !== null
            || $this->getMaximumImageWidth() !== null
            || $this->getMinimumImageHeight() !== null
            || $this->getMaximumImageHeight() !== null
        ) {
            foreach ($this->getValue() as $file) {
                $imagesize = \getimagesize($file->getLocation());

                if ($this->getMinimumImageWidth() !== null && $this->getMinimumImageWidth() > $imagesize[0]) {
                    $this->addValidationError(new FormFieldValidationError(
                        'minimumImageWidth',
                        'wcf.form.field.upload.error.minimumImageWidth',
                        [
                            'minimumImageWidth' => $this->getMinimumImageWidth(),
                            'file' => $file,
                        ]
                    ));
                } elseif ($this->getMaximumImageWidth() !== null && $imagesize[0] > $this->getMaximumImageWidth()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumImageWidth',
                        'wcf.form.field.upload.error.maximumImageWidth',
                        [
                            'maximumImageWidth' => $this->getMaximumImageWidth(),
                            'file' => $file,
                        ]
                    ));
                }

                if ($this->getMinimumImageHeight() !== null && $this->getMinimumImageHeight() > $imagesize[1]) {
                    $this->addValidationError(new FormFieldValidationError(
                        'minimumImageHeight',
                        'wcf.form.field.upload.error.minimumImageHeight',
                        [
                            'minimumImageHeight' => $this->getMinimumImageHeight(),
                            'file' => $file,
                        ]
                    ));
                } elseif ($this->getMaximumImageHeight() !== null && $imagesize[0] > $this->getMaximumImageHeight()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumImageHeight',
                        'wcf.form.field.upload.error.maximumImageHeight',
                        [
                            'maximumImageHeight' => $this->getMaximumImageHeight(),
                            'file' => $file,
                        ]
                    ));
                }
            }
        }
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getHtml()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        return parent::getHtml();
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getFieldHtml()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        return parent::getFieldHtml();
    }

    /**
     * @inheritDoc
     *
     * @throws \InvalidArgumentException    if the getter for the value provides invalid values
     */
    public function updatedObject(array $data, IStorableObject $object, $loadValues = true)
    {
        if ($loadValues) {
            // first check, whether an getter for the field exists
            if (\method_exists($object, 'get' . \ucfirst($this->getObjectProperty()) . 'UploadFileLocations')) {
                $value = \call_user_func([
                    $object,
                    'get' . \ucfirst($this->getObjectProperty()) . 'UploadFileLocations',
                ]);
                $method = "method '" . \get_class($object) . "::get" . \ucfirst($this->getObjectProperty()) . "UploadFileLocations()'";
            } elseif (\method_exists($object, 'get' . \ucfirst($this->getObjectProperty()))) {
                $value = \call_user_func([$object, 'get' . \ucfirst($this->getObjectProperty())]);
                $method = "method '" . \get_class($object) . "::get" . \ucfirst($this->getObjectProperty()) . "()'";
            } else {
                $value = $data[$this->getObjectProperty()];
                $method = "variable '" . \get_class($object) . "::$" . $this->getObjectProperty() . "'";
            }

            if (\is_array($value)) {
                $value = \array_map(function ($v) use ($method) {
                    if (!\is_string($v) || !\file_exists($v)) {
                        throw new \InvalidArgumentException(
                            "The " . $method . " must return an array of strings with the file locations."
                        );
                    }

                    return new UploadFile(
                        $v,
                        \basename($v),
                        ImageUtil::isImage($v, \basename($v), $this->svgImageAllowed()),
                        true,
                        $this->svgImageAllowed()
                    );
                }, $value);

                $this->value($value);
            } else {
                throw new \InvalidArgumentException(
                    "The " . $method . " must return an array of strings with the file locations."
                );
            }
        }

        return $this;
    }

    /**
     * @inheritDoc
     *
     * @param UploadFile[] $value
     *
     * @throws      \InvalidArgumentException       if the value is not an array
     * @throws      \InvalidArgumentException       if the value contains objects, which are not an instance of UploadFile
     */
    public function value($value)
    {
        if (!\is_array($value)) {
            throw new \InvalidArgumentException('$value must be an array.');
        }

        foreach ($value as $file) {
            if (!($file instanceof UploadFile)) {
                throw new \InvalidArgumentException(
                    'All given files must be an instance of ' . UploadFile::class . '.'
                );
            }
        }

        if ($this->isPopulated) {
            UploadHandler::getInstance()->registerFilesByField($this->getPrefixedId(), $value);
        } else {
            $this->values = $value;
        }
    }

    /**
     * @inheritDoc
     */
    public function hasSaveValue()
    {
        return false;
    }

    /**
     * @inheritDoc
     */
    public function cleanup()
    {
        if (!$this->cleaned) {
            $this->unregisterField();
            $this->cleaned = true;
        }

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function populate()
    {
        parent::populate();

        UploadHandler::getInstance()->registerUploadField(
            $this->buildUploadField(),
            $this->getDocument()->getRequestData()
        );

        if (!empty($this->values)) {
            UploadHandler::getInstance()->registerFilesByField($this->getPrefixedId(), $this->values);
        }

        $this->getDocument()->getDataHandler()->addProcessor(new CustomFormDataProcessor(
            'upload',
            function (IFormDocument $document, array $parameters) {
                $parameters[$this->getObjectProperty()] = $this->getValue();
                $parameters[$this->getObjectProperty() . '_removedFiles'] = $this->getRemovedFiles(true);

                return $parameters;
            }
        ));

        return $this;
    }

    /**
     * @inheritDoc
     *
     * @throws      \LogicException       if the field has already been initialized
     */
    public function maximum($maximum = null)
    {
        if ($this->isRegistered()) {
            throw new \LogicException(
                'The upload field has already been registered. Therefore no modifications are allowed.'
            );
        }

        return $this->traitMaximum($maximum);
    }

    /**
     * Sets the maximum filesize for each upload. If `null` is passed, the
     * maximum filesize is removed.
     *
     * @param null|number $maximumFilesize maximum filesize
     * @return  static                      this field
     *<commit_msg>Add lazy UploadFormField registration<commit_after><?php

namespace wcf\system\form\builder\field;

use wcf\data\IStorableObject;
use wcf\system\file\upload\UploadField;
use wcf\system\file\upload\UploadFile;
use wcf\system\file\upload\UploadHandler;
use wcf\system\form\builder\data\processor\CustomFormDataProcessor;
use wcf\system\form\builder\field\validation\FormFieldValidationError;
use wcf\system\form\builder\IFormDocument;
use wcf\util\ImageUtil;

/**
 * Implementation of a form field for to uploads.
 *
 * @author  <NAME>
 * @copyright   2001-2019 WoltLab GmbH
 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
 * @package WoltLabSuite\Core\System\Form\Builder\Field
 * @since   5.2
 */
class UploadFormField extends AbstractFormField
{
    use TMaximumFormField {
        maximum as traitMaximum;
    }
    use TMinimumFormField;

    /**
     * @inheritDoc
     */
    protected $javaScriptDataHandlerModule = 'WoltLabSuite/Core/Form/Builder/Field/Value';

    /**
     * This flag indicates whether only images can uploaded via this field.
     * <strong>Attention</strong>: SVG images can contain bad code, therefore do not
     * use this option, outside the acp or check the file whether remote code is contained.
     * @var bool
     */
    protected $imageOnly = false;

    /**
     * This flag indicates whether SVG images are treated as image in the image only mode.
     * @var bool
     */
    protected $allowSvgImage = false;

    /**
     * Acceptable file types.
     * @var null|string[]
     * @since 5.3
     */
    protected $acceptableFiles;

    /**
     * maximum filesize for each uploaded file
     * @var null|number
     */
    protected $maximumFilesize;

    /**
     * minimum image width for each uploaded file
     * @var null|number
     */
    protected $minimumImageWidth;

    /**
     * maximum image width for each uploaded file
     * @var null|number
     */
    protected $maximumImageWidth;

    /**
     * minimum image height for each uploaded file
     * @var null|number
     */
    protected $minimumImageHeight;

    /**
     * maximum image height for each uploaded file
     * @var null|number
     */
    protected $maximumImageHeight;

    /**
     * @inheritDoc
     */
    protected $templateName = '__uploadFormField';

    /**
     * Array of temporary values, which are assigned, after the method `populate` are called.
     * @var array
     */
    private $values = [];

    /**
     * Flag whether the field is already unregistered.
     * @var bool
     */
    private $cleaned = false;

    /**
     * Flag whether the field is already registered.
     * @var bool
     * @since 5.4
     */
    private $isRegistered = false;

    /**
     * Unregisters the current field in the upload handler.
     */
    private function unregisterField()
    {
        if (UploadHandler::getInstance()->isRegisteredFieldId($this->getPrefixedId())) {
            UploadHandler::getInstance()->unregisterUploadField($this->getPrefixedId());

            $this->isRegistered = false;
        }
    }

    /**
     * Builds the UploadField class.
     *
     * @return      UploadField
     */
    protected function buildUploadField()
    {
        $uploadField = new UploadField($this->getPrefixedId());
        $uploadField->maxFiles = $this->getMaximum();
        $uploadField->setImageOnly($this->isImageOnly());
        if ($this->isImageOnly()) {
            $uploadField->setAllowSvgImage($this->svgImageAllowed());
        }
        $uploadField->setAcceptableFiles($this->getAcceptableFiles());

        return $uploadField;
    }

    /**
     * Returns true, iff the current field is already registered.
     *
     * @return bool
     */
    private function isRegistered()
    {
        return $this->isRegistered;
    }

    /**
     * @inheritDoc
     * @return      UploadFile[]
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getValue()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        if (!$this->isRegistered) {
            $this->registerField();
        }

        return UploadHandler::getInstance()->getFilesByFieldId($this->getPrefixedId());
    }

    /**
     * Returns the removed files for the field.
     *
     * @param bool $processFiles
     * @return      UploadFile[]
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getRemovedFiles($processFiles = false)
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling the method.");
        }

        if (!$this->isRegistered) {
            $this->registerField();
        }

        return UploadHandler::getInstance()->getRemovedFiledByFieldId($this->getPrefixedId(), $processFiles);
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function readValue()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function validate()
    {
        parent::validate();

        if (empty($this->getValue())) {
            if ($this->isRequired()) {
                $this->addValidationError(new FormFieldValidationError('empty'));
            }
        }

        if ($this->getMinimum() !== null && \count($this->getValue()) < $this->getMinimum()) {
            $this->addValidationError(new FormFieldValidationError(
                'minimum',
                'wcf.form.field.upload.error.minimum',
                ['minimum' => $this->getMinimum()]
            ));
        } elseif ($this->getMaximum() !== null && \count($this->getValue()) > $this->getMaximum()) {
            $this->addValidationError(new FormFieldValidationError(
                'maximum',
                'wcf.form.field.upload.error.maximum',
                ['maximum' => $this->getMaximum()]
            ));
        }

        if ($this->getMaximumFilesize() !== null) {
            foreach ($this->getValue() as $file) {
                $filesize = \filesize($file->getLocation());
                if ($filesize > $this->getMaximumFilesize()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumFilesize',
                        'wcf.form.field.upload.error.maximumFilesize',
                        [
                            'maximumFilesize' => $this->getMaximumFilesize(),
                            'file' => $file,
                        ]
                    ));
                }
            }
        }

        if (
            $this->getMinimumImageWidth() !== null
            || $this->getMaximumImageWidth() !== null
            || $this->getMinimumImageHeight() !== null
            || $this->getMaximumImageHeight() !== null
        ) {
            foreach ($this->getValue() as $file) {
                $imagesize = \getimagesize($file->getLocation());

                if ($this->getMinimumImageWidth() !== null && $this->getMinimumImageWidth() > $imagesize[0]) {
                    $this->addValidationError(new FormFieldValidationError(
                        'minimumImageWidth',
                        'wcf.form.field.upload.error.minimumImageWidth',
                        [
                            'minimumImageWidth' => $this->getMinimumImageWidth(),
                            'file' => $file,
                        ]
                    ));
                } elseif ($this->getMaximumImageWidth() !== null && $imagesize[0] > $this->getMaximumImageWidth()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumImageWidth',
                        'wcf.form.field.upload.error.maximumImageWidth',
                        [
                            'maximumImageWidth' => $this->getMaximumImageWidth(),
                            'file' => $file,
                        ]
                    ));
                }

                if ($this->getMinimumImageHeight() !== null && $this->getMinimumImageHeight() > $imagesize[1]) {
                    $this->addValidationError(new FormFieldValidationError(
                        'minimumImageHeight',
                        'wcf.form.field.upload.error.minimumImageHeight',
                        [
                            'minimumImageHeight' => $this->getMinimumImageHeight(),
                            'file' => $file,
                        ]
                    ));
                } elseif ($this->getMaximumImageHeight() !== null && $imagesize[0] > $this->getMaximumImageHeight()) {
                    $this->addValidationError(new FormFieldValidationError(
                        'maximumImageHeight',
                        'wcf.form.field.upload.error.maximumImageHeight',
                        [
                            'maximumImageHeight' => $this->getMaximumImageHeight(),
                            'file' => $file,
                        ]
                    ));
                }
            }
        }
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getHtml()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        if (!$this->isRegistered) {
            $this->registerField();
        }

        return parent::getHtml();
    }

    /**
     * @inheritDoc
     * @throws      \BadMethodCallException         if the method is called, before the field is populated
     */
    public function getFieldHtml()
    {
        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field must be populated, before calling this method.");
        }

        if (!$this->isRegistered) {
            $this->registerField();
        }

        return parent::getFieldHtml();
    }

    /**
     * @inheritDoc
     *
     * @throws \InvalidArgumentException    if the getter for the value provides invalid values
     */
    public function updatedObject(array $data, IStorableObject $object, $loadValues = true)
    {
        if ($loadValues) {
            // first check, whether an getter for the field exists
            if (\method_exists($object, 'get' . \ucfirst($this->getObjectProperty()) . 'UploadFileLocations')) {
                $value = \call_user_func([
                    $object,
                    'get' . \ucfirst($this->getObjectProperty()) . 'UploadFileLocations',
                ]);
                $method = "method '" . \get_class($object) . "::get" . \ucfirst($this->getObjectProperty()) . "UploadFileLocations()'";
            } elseif (\method_exists($object, 'get' . \ucfirst($this->getObjectProperty()))) {
                $value = \call_user_func([$object, 'get' . \ucfirst($this->getObjectProperty())]);
                $method = "method '" . \get_class($object) . "::get" . \ucfirst($this->getObjectProperty()) . "()'";
            } else {
                $value = $data[$this->getObjectProperty()];
                $method = "variable '" . \get_class($object) . "::$" . $this->getObjectProperty() . "'";
            }

            if (\is_array($value)) {
                $value = \array_map(function ($v) use ($method) {
                    if (!\is_string($v) || !\file_exists($v)) {
                        throw new \InvalidArgumentException(
                            "The " . $method . " must return an array of strings with the file locations."
                        );
                    }

                    return new UploadFile(
                        $v,
                        \basename($v),
                        ImageUtil::isImage($v, \basename($v), $this->svgImageAllowed()),
                        true,
                        $this->svgImageAllowed()
                    );
                }, $value);

                $this->value($value);
            } else {
                throw new \InvalidArgumentException(
                    "The " . $method . " must return an array of strings with the file locations."
                );
            }
        }

        return $this;
    }

    /**
     * @inheritDoc
     *
     * @param UploadFile[] $value
     *
     * @throws      \InvalidArgumentException       if the value is not an array
     * @throws      \InvalidArgumentException       if the value contains objects, which are not an instance of UploadFile
     */
    public function value($value)
    {
        if (!\is_array($value)) {
            throw new \InvalidArgumentException('$value must be an array.');
        }

        foreach ($value as $file) {
            if (!($file instanceof UploadFile)) {
                throw new \InvalidArgumentException(
                    'All given files must be an instance of ' . UploadFile::class . '.'
                );
            }
        }

        if ($this->isRegistered) {
            UploadHandler::getInstance()->registerFilesByField($this->getPrefixedId(), $value);
        } else {
            $this->values = $value;
        }
    }

    /**
     * @inheritDoc
     */
    public function hasSaveValue()
    {
        return false;
    }

    /**
     * @inheritDoc
     */
    public function cleanup()
    {
        if (!$this->cleaned) {
            $this->unregisterField();
            $this->cleaned = true;
        }

        return $this;
    }

    /**
     * @inheritDoc
     */
    public function populate()
    {
        parent::populate();

        $this->getDocument()->getDataHandler()->addProcessor(new CustomFormDataProcessor(
            'upload',
            function (IFormDocument $document, array $parameters) {
                $parameters[$this->getObjectProperty()] = $this->getValue();
                $parameters[$this->getObjectProperty() . '_removedFiles'] = $this->getRemovedFiles(true);

                return $parameters;
            }
        ));

        return $this;
    }

    /**
     * @since 5.4
     * @throws \BadMethodCallException if the field is already registered
     */
    private function registerField(): void
    {
        if ($this->isRegistered) {
            throw new \BadMethodCallException("The field is already registered.");
        }

        if (!$this->isPopulated) {
            throw new \BadMethodCallException("The field is not populated yet.");
        }

        UploadHandler::getInstance()->registerUploadField(
            $this->buildUploadField(),
            $this->getDocument()->getRequestData()
        );

        if (!empty($this->values)) {
            UploadHandler::getInstance()->registerFilesByField($this->getPrefixedId(), $this->values);
        }

        $this->isRegistered = true;
    }

    /**
     * @inheritDoc
     *
     * @throws      \LogicException       if the field has already been initialized
     */
    public function maximum($maximum = null)
    {
        if ($this->isRegistered()) {
            throw new \LogicException(
                'The upload field has already been registered. Therefore no modifications are allowed.'
            );
        }

        return $this->traitMaximum($maximum);
    }

    /**
     * Sets the maximum filesize for each upload. If `null` is passed, the
     * maximum filesize is removed.
     *
     * @param null|number $maximumFilesize maximum filesize
     * @return  static                      this field
     *
{'fraction_non_alphanumeric': 0.12192353837673077, 'fraction_numerical': 0.001167353027011252, 'mean_word_length': 1.7140719880313298, 'pattern_counts': {'":': 6, '<': 15, '<?xml version=': 0, '>': 259, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7592890', 'n_tokens_mistral': 8143, 'n_tokens_neox': 7716, 'n_words': 1766}