From: Matthias Schmidt Date: Sat, 7 Dec 2019 10:40:44 +0000 (+0100) Subject: Also make updated object available during post requests in form builder X-Git-Tag: 5.2.0_RC_1~10 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=7b752ad07448aa9c3964b0595d157b680e5d4d53;p=GitHub%2FWoltLab%2FWCF.git Also make updated object available during post requests in form builder Close #3117 --- diff --git a/wcfsetup/install/files/lib/form/AbstractFormBuilderForm.class.php b/wcfsetup/install/files/lib/form/AbstractFormBuilderForm.class.php index 3647ea1fe4..49e8f68027 100644 --- a/wcfsetup/install/files/lib/form/AbstractFormBuilderForm.class.php +++ b/wcfsetup/install/files/lib/form/AbstractFormBuilderForm.class.php @@ -117,9 +117,7 @@ abstract class AbstractFormBuilderForm extends AbstractForm { */ public function readData() { if ($this->formObject !== null) { - if (empty($_POST)) { - $this->setFormObjectData(); - } + $this->setFormObjectData(); } else if ($this->formAction === 'edit') { throw new \UnexpectedValueException("Missing form object to update."); @@ -209,7 +207,7 @@ abstract class AbstractFormBuilderForm extends AbstractForm { * Sets the form data based on the current form object. */ protected function setFormObjectData() { - $this->form->loadValuesFromObject($this->formObject); + $this->form->updatedObject($this->formObject, empty($_POST)); } /** diff --git a/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php b/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php index 509b339393..8fe3d7a93d 100644 --- a/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php @@ -530,7 +530,7 @@ class FormDocument implements IFormDocument { /** * @inheritDoc */ - public function loadValuesFromObject(IStorableObject $object) { + public function updatedObject(IStorableObject $object, $loadValues = true) { if ($this->formMode === null) { $this->formMode(self::FORM_MODE_UPDATE); } @@ -543,7 +543,7 @@ class FormDocument implements IFormDocument { if ($node instanceof IFormField) { if ($node->getObjectProperty() !== $node->getId()) { try { - $node->loadValue($data, $object); + $node->updatedObject($data, $object, $loadValues); } catch (\InvalidArgumentException $e) { // if an object property is explicitly set, @@ -552,11 +552,11 @@ class FormDocument implements IFormDocument { } } else { - $node->loadValue($data, $object); + $node->updatedObject($data, $object, $loadValues); } } else if ($node instanceof IFormContainer) { - $node->loadValues($data, $object); + $node->updatedObject($data, $object, $loadValues); } } } diff --git a/wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php b/wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php index df0cb38ba9..7025fc9495 100644 --- a/wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php @@ -288,15 +288,17 @@ interface IFormDocument extends IFormParentNode { public function invalid($invalid = true); /** - * Loads the field values from the given object and returns this document. + * Sets the updated object (and loads the field values from the given object) and returns + * this document. * - * Per default, for each field, `IFormField::loadValueFromObject()` is called. + * Per default, for each field, `IFormField::updatedObject()` is called. * This method automatically sets the form mode to `self::FORM_MODE_UPDATE`. * - * @param IStorableObject $object object used to load field values + * @param IStorableObject $object updated object + * @param boolean $loadValues indicates if the object's values are loaded * @return static this document */ - public function loadValuesFromObject(IStorableObject $object); + public function updatedObject(IStorableObject $object, $loadValues = true); /** * Sets the `method` property of the HTML `form` element and returns this document. diff --git a/wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php b/wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php index 9d1bb1b8ef..008a3cda3b 100644 --- a/wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php @@ -61,7 +61,7 @@ class FormContainer implements IFormContainer { /** * @inheritDoc */ - public function loadValues(array $data, IStorableObject $object) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { // does nothing return $this; diff --git a/wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php b/wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php index fb3cb77a62..efdbbb9420 100644 --- a/wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php @@ -16,15 +16,17 @@ use wcf\system\form\builder\IFormParentNode; */ interface IFormContainer extends IFormChildNode, IFormElement, IFormParentNode { /** - * This method is called by `IFormDocument::loadValue()` to inform the container that object - * data is being loaded. + * Informs the form container of the updated object and this method is called by + * `IFormDocument::updatedObject()` to inform the container that object data is being loaded. + * + * This method is *not* intended to generally call `IFormField::updatedObject()` on its form field + * children as these methods are already called by `IFormDocument::updatedObject()`. * - * This method is *not* intended to generally call `IFormField::loadValue()` on its form field - * children as these methods are already called by `IFormDocument::loadValuesFromObject()`. - * * @param array $data data from which the values are extracted * @param IStorableObject $object object the data belongs to + * @param bool $loadValues + * * @return static this container */ - public function loadValues(array $data, IStorableObject $object); + public function updatedObject(array $data, IStorableObject $object, $loadValues = true); } diff --git a/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php b/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php index 007ffa3f9c..51c645528c 100644 --- a/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php @@ -341,22 +341,12 @@ class WysiwygFormContainer extends FormContainer { /** * @inheritDoc */ - public function loadValues(array $data, IStorableObject $object) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { $this->objectId = $object->{$object::getDatabaseTableIndexName()}; - if ($this->attachmentData !== null) { - // updated attachment handler with object id - $this->attachmentField->attachmentHandler( - new AttachmentHandler( - $this->attachmentData['objectType'], - $this->getObjectId(), - '.', - $this->attachmentData['parentObjectID'] - ) - ); - } + $this->setAttachmentHandler(); - return parent::loadValues($data, $object); + return parent::updatedObject($data, $object); } /** @@ -447,16 +437,7 @@ class WysiwygFormContainer extends FormContainer { ]); if ($this->attachmentData !== null) { - $this->attachmentField->attachmentHandler( - // the temporary hash may not be empty (at the same time as the - // object id) and it will be changed anyway by the called method - new AttachmentHandler( - $this->attachmentData['objectType'], - $this->getObjectId(), - '.', - $this->attachmentData['parentObjectID'] - ) - ); + $this->setAttachmentHandler(); } $this->getDocument()->addButton( @@ -523,6 +504,22 @@ class WysiwygFormContainer extends FormContainer { return $this; } + /** + * Sets the attachment handler of the attachment form field. + */ + protected function setAttachmentHandler() { + if ($this->attachmentData !== null) { + $this->attachmentField->attachmentHandler( + new AttachmentHandler( + $this->attachmentData['objectType'], + $this->getObjectId(), + '.', + $this->attachmentData['parentObjectID'] + ) + ); + } + } + /** * Sets if mentions are supported by the editor field and returns this form container. * diff --git a/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygPollFormContainer.class.php b/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygPollFormContainer.class.php index 250ebd6027..69942e72b9 100644 --- a/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygPollFormContainer.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygPollFormContainer.class.php @@ -226,8 +226,8 @@ class WysiwygPollFormContainer extends FormContainer implements IObjectTypeFormN /** * @inheritDoc */ - public function loadValues(array $data, IStorableObject $object) { - if ($data instanceof IPollContainer && $data->getPollID() !== null) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { + if ($loadValues && $data instanceof IPollContainer && $data->getPollID() !== null) { $this->poll = new Poll($data->getPollID()); if (!$this->poll->pollID) { $this->poll = null; @@ -247,7 +247,7 @@ class WysiwygPollFormContainer extends FormContainer implements IObjectTypeFormN $this->getSortByVotesField()->value($this->poll->sortByVotes); } - return parent::loadValues($data, $object); + return parent::updatedObject($data, $object); } /** diff --git a/wcfsetup/install/files/lib/system/form/builder/field/AbstractFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/AbstractFormField.class.php index b086ce2256..6ae7bd7b27 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/AbstractFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/AbstractFormField.class.php @@ -203,8 +203,8 @@ abstract class AbstractFormField implements IFormField { /** * @inheritDoc */ - public function loadValue(array $data, IStorableObject $object) { - if (isset($data[$this->getObjectProperty()])) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { + if ($loadValues && isset($data[$this->getObjectProperty()])) { $this->value($data[$this->getObjectProperty()]); } diff --git a/wcfsetup/install/files/lib/system/form/builder/field/IFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/IFormField.class.php index 0863de42d8..a43ffa7934 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/IFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/IFormField.class.php @@ -124,16 +124,18 @@ interface IFormField extends IFormChildNode, IFormElement { public function isRequired(); /** - * Loads the field value from the given data and returns this field. + * Informs the form field of the updated object (and loads the field value from the given data) + * and returns this field. * * It is important to extract the value from the `$data` array instead of getting it directly * from the object as the entries of `$data` have been processed by the data processors. * - * @param array $data data from which the value is extracted - * @param IStorableObject $object object the data belongs to + * @param array $data object data + * @param IStorableObject $object updated object + * @param bool $loadValues indicates if object data is loaded * @return static this field */ - public function loadValue(array $data, IStorableObject $object); + public function updatedObject(array $data, IStorableObject $object, $loadValues = true); /** * Sets the name of the object property this field represents. If an empty diff --git a/wcfsetup/install/files/lib/system/form/builder/field/TI18nFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/TI18nFormField.class.php index 601920bb96..8546b03e26 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/TI18nFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/TI18nFormField.class.php @@ -249,8 +249,8 @@ trait TI18nFormField { /** * @inheritDoc */ - public function loadValueFromObject(array $data, IStorableObject $object) { - if (isset($data[$this->getObjectProperty()])) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { + if ($loadValues && isset($data[$this->getObjectProperty()])) { $value = $data[$this->getObjectProperty()]; if ($this->isI18n()) { diff --git a/wcfsetup/install/files/lib/system/form/builder/field/UploadFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/UploadFormField.class.php index 2e725cc9e7..2330f81cc5 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/UploadFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/UploadFormField.class.php @@ -278,33 +278,35 @@ class UploadFormField extends AbstractFormField { * * @throws \InvalidArgumentException if the getter for the value provides invalid values */ - public function loadValue(array $data, IStorableObject $object) { - // 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()'"; - } - else if (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), UploadHandler::isValidImage($v, basename($v), $this->svgImageAllowed()), true, $this->svgImageAllowed()); - }, $value); + 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()'"; + } + else if (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() . "'"; + } - $this->value($value); - } - else { - throw new \InvalidArgumentException("The " . $method . " must return an array of strings with the file locations."); + 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), UploadHandler::isValidImage($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; diff --git a/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php index 61fb25ef78..d642904a0a 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php @@ -115,7 +115,7 @@ class AclFormField extends AbstractFormField implements IObjectTypeFormNode { /** * @inheritDoc */ - public function loadValue(array $data, IStorableObject $object) { + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { $this->objectID = $object->{$object::getDatabaseTableIndexName()}; if ($this->objectID === null) { diff --git a/wcfsetup/install/files/lib/system/form/builder/field/label/LabelFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/label/LabelFormField.class.php index f1ba60d6d2..ce3d6476a7 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/label/LabelFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/label/LabelFormField.class.php @@ -96,25 +96,27 @@ class LabelFormField extends AbstractFormField implements IObjectTypeFormNode { /** * @inheritDoc */ - public function loadValue(array $data, IStorableObject $object) { - $objectTypeID = $this->getObjectType()->objectTypeID; - $objectID = $object->{$object::getDatabaseTableIndexName()}; - - if (!isset(static::$loadedLabels[$objectTypeID])) { - static::$loadedLabels[$objectTypeID] = []; - } - if (!isset(static::$loadedLabels[$objectTypeID][$objectID])) { - static::$loadedLabels[$objectTypeID][$objectID] = LabelHandler::getInstance()->getAssignedLabels( - $objectTypeID, - [$objectID] - )[$objectID]; - } - - $labelIDs = $this->getLabelGroup()->getLabelIDs(); - /** @var Label $label */ - foreach (static::$loadedLabels[$objectTypeID][$objectID] as $label) { - if (in_array($label->labelID, $labelIDs)) { - $this->value($label->labelID); + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { + if ($loadValues) { + $objectTypeID = $this->getObjectType()->objectTypeID; + $objectID = $object->{$object::getDatabaseTableIndexName()}; + + if (!isset(static::$loadedLabels[$objectTypeID])) { + static::$loadedLabels[$objectTypeID] = []; + } + if (!isset(static::$loadedLabels[$objectTypeID][$objectID])) { + static::$loadedLabels[$objectTypeID][$objectID] = LabelHandler::getInstance()->getAssignedLabels( + $objectTypeID, + [$objectID] + )[$objectID]; + } + + $labelIDs = $this->getLabelGroup()->getLabelIDs(); + /** @var Label $label */ + foreach (static::$loadedLabels[$objectTypeID][$objectID] as $label) { + if (in_array($label->labelID, $labelIDs)) { + $this->value($label->labelID); + } } } diff --git a/wcfsetup/install/files/lib/system/form/builder/field/tag/TagFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/tag/TagFormField.class.php index b622bb30e5..133b15174f 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/tag/TagFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/tag/TagFormField.class.php @@ -63,29 +63,31 @@ class TagFormField extends AbstractFormField implements IObjectTypeFormNode { /** * @inheritDoc */ - public function loadValue(array $data, IStorableObject $object) { - $objectID = $object->{$object::getDatabaseTableIndexName()}; - - if ($objectID === null) { - throw new \UnexpectedValueException("Cannot read object id from object of class '" . get_class($object). "'."); - } - - if ($this->getObjectType() === null) { - throw new \UnexpectedValueException("Missing taggable object type."); - } - - $languageIDs = []; - - /** @noinspection PhpUndefinedFieldInspection */ - if (isset($data['languageID'])) { - $languageIDs[] = $data['languageID']; - } - - $tags = TagEngine::getInstance()->getObjectTags($this->getObjectType()->objectType, $objectID, $languageIDs); - - $this->value = []; - foreach ($tags as $tag) { - $this->value[] = $tag->name; + public function updatedObject(array $data, IStorableObject $object, $loadValues = true) { + if ($loadValues) { + $objectID = $object->{$object::getDatabaseTableIndexName()}; + + if ($objectID === null) { + throw new \UnexpectedValueException("Cannot read object id from object of class '" . get_class($object). "'."); + } + + if ($this->getObjectType() === null) { + throw new \UnexpectedValueException("Missing taggable object type."); + } + + $languageIDs = []; + + /** @noinspection PhpUndefinedFieldInspection */ + if (isset($data['languageID'])) { + $languageIDs[] = $data['languageID']; + } + + $tags = TagEngine::getInstance()->getObjectTags($this->getObjectType()->objectType, $objectID, $languageIDs); + + $this->value = []; + foreach ($tags as $tag) { + $this->value[] = $tag->name; + } } return $this;