Also make updated object available during post requests in form builder
authorMatthias Schmidt <gravatronics@live.com>
Sat, 7 Dec 2019 10:40:44 +0000 (11:40 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sat, 7 Dec 2019 10:40:44 +0000 (11:40 +0100)
Close #3117

14 files changed:
wcfsetup/install/files/lib/form/AbstractFormBuilderForm.class.php
wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php
wcfsetup/install/files/lib/system/form/builder/IFormDocument.class.php
wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/container/IFormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygFormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/container/wysiwyg/WysiwygPollFormContainer.class.php
wcfsetup/install/files/lib/system/form/builder/field/AbstractFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/IFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/TI18nFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/UploadFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/acl/AclFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/label/LabelFormField.class.php
wcfsetup/install/files/lib/system/form/builder/field/tag/TagFormField.class.php

index 3647ea1fe4903f39986de02bcf7897e3ac9f1395..49e8f6802789eb6b3d06f5a7c96bcf5ace2c6d72 100644 (file)
@@ -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));
        }
        
        /**
index 509b33939332c5e811128cf232de59332653929a..8fe3d7a93d0a0063a54ab6822b87c6509759c6ed 100644 (file)
@@ -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);
                                }
                        }
                }
index df0cb38ba93d742c0dcef68109ef9b080bdcc459..7025fc9495d3cef6b96627d9003c2c54d7d2edb4 100644 (file)
@@ -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.
index 9d1bb1b8efdd18c83088a7ecf5cb0397f80eba4e..008a3cda3b448a7c9fe825e9c01587aac2fa7f88 100644 (file)
@@ -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;
index fb3cb77a62e5986f4bf4061940f14f20b55b9547..efdbbb942005547009438ebbe903122d96de2517 100644 (file)
@@ -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);
 }
index 007ffa3f9ce4e9f8766c63f0a65f30359db6f7fd..51c645528c77ff0bc152f29a7580db180e2cd948 100644 (file)
@@ -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.
         * 
index 250ebd60275c305731818b60e354c5251b030366..69942e72b9c72bc84b2c56197f4a5ddb776f741e 100644 (file)
@@ -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);
        }
        
        /**
index b086ce22560bbdab179d9c767f63ccae3c0cb471..6ae7bd7b27cbe4a9ebde80dc05e1d0b0f260a17c 100644 (file)
@@ -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()]);
                }
                
index 0863de42d8f33197ea60f5056c66dc70636934b0..a43ffa7934460515a319a7bead878454dea28686 100644 (file)
@@ -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
index 601920bb96e8f48de152c19c915d1b08dfad5960..8546b03e2625791a9f9a23b7acfcee95e8ea6e45 100644 (file)
@@ -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()) {
index 2e725cc9e77523c6cc3bf7bafa3641085ebdb275..2330f81cc53a667bb0dde9fe4d4d2a119d485925 100644 (file)
@@ -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;
index 61fb25ef7809651740d642f1d9c2212ec492b4c2..d642904a0a12389021851a407f37d576fde9bcaa 100644 (file)
@@ -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) {
index f1ba60d6d2653b4ef6d0762bdb8777edb8628d33..ce3d6476a7dde0c6d598c999703c4db08abdbba6 100644 (file)
@@ -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);
+                               }
                        }
                }
                
index b622bb30e5d11e928f433c35c01da3222d22b23c..133b15174fdcbb4319d4b7da49cbfef7e28a338b 100644 (file)
@@ -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;