Add custom form field data processor
authorMatthias Schmidt <gravatronics@live.com>
Sun, 31 Dec 2017 16:44:43 +0000 (17:44 +0100)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 31 Dec 2017 16:44:58 +0000 (17:44 +0100)
See #2509

wcfsetup/install/files/lib/acp/form/DevtoolsFormBuilderTestForm.class.php
wcfsetup/install/files/lib/system/form/builder/field/data/CustomFormFieldDataProcessor.class.php [new file with mode: 0644]

index fca241919a5f077baeee3697bc950c531f0e214d..98ebf90c385414776c8525f3be8f4746d45201f1 100644 (file)
@@ -6,6 +6,7 @@ use wcf\system\form\builder\container\FormContainer;
 use wcf\system\form\builder\container\TabFormContainer;
 use wcf\system\form\builder\container\TabMenuFormContainer;
 use wcf\system\form\builder\field\BooleanFormField;
+use wcf\system\form\builder\field\data\CustomFormFieldDataProcessor;
 use wcf\system\form\builder\field\validation\FormFieldValidationError;
 use wcf\system\form\builder\field\validation\FormFieldValidator;
 use wcf\system\form\builder\FormDocument;
@@ -104,6 +105,16 @@ class DevtoolsFormBuilderTestForm extends AbstractForm {
                                                ->label('Tab 2')
                                ])
                ]);
+               
+               $this->form->getDataHandler()->add(new CustomFormFieldDataProcessor('isDisabledToString', function(IFormDocument $document, array $parameters) {
+                       unset($parameters['data']['isDisabled']);
+                       
+                       /** @var null|BooleanFormField $node */
+                       $node = $document->getNodeById('isDisabled');
+                       $parameters['isDisabled'] = $node->getValue() ? 'true' : 'false';
+                       
+                       return $parameters;
+               }));
        }
        
        /**
diff --git a/wcfsetup/install/files/lib/system/form/builder/field/data/CustomFormFieldDataProcessor.class.php b/wcfsetup/install/files/lib/system/form/builder/field/data/CustomFormFieldDataProcessor.class.php
new file mode 100644 (file)
index 0000000..aa29a3b
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+namespace wcf\system\form\builder\field\data;
+use wcf\system\form\builder\IFormDocument;
+
+/**
+ * Field data processor implementation that supports a custom processor callable.
+ * 
+ * @author     Matthias Schmidt
+ * @copyright  2001-2018 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Form\Builder\Field\Data
+ * @since      3.2
+ */
+class CustomFormFieldDataProcessor implements IFormFieldDataProcessor {
+       /**
+        * processor id primarily used for error messages
+        * @var string
+        */
+       protected $id;
+       
+       /**
+        * callable processing the data
+        * @var callable 
+        */
+       protected $processor;
+       
+       /**
+        * Initializes a new CustomFormFieldDataProcessor object.
+        * 
+        * @param       string          $id             processor id primarily used for error messages, does not have to be unique
+        * @param       callable        $processor      processor callable
+        * 
+        * @throws      \InvalidArgumentException       if either id or processor callable are invalid
+        */
+       public function __construct($id, callable $processor) {
+               if (!is_string($id)) {
+                       throw new \InvalidArgumentException("Given id is no string, " . gettype($id) . " given.");
+               }
+               
+               if (preg_match('~^[a-z][A-z0-9-]*$~', $id) !== 1) {
+                       throw new \InvalidArgumentException("Invalid id '{$id}' given.");
+               }
+               
+               $this->id = $id;
+               
+               // validate prcoessor function
+               $parameters = (new \ReflectionFunction($processor))->getParameters();
+               if (count($parameters) !== 2) {
+                       throw new \InvalidArgumentException(
+                               "The processor function must expect two parameters, instead " . count($parameters) .
+                               " parameter" . (count($parameters) !== 1 ? 's' : '') . " are expected."
+                       );
+               }
+               $parameterClass = $parameters[0]->getClass();
+               if ($parameterClass === null || ($parameterClass->getName() !== IFormDocument::class && !is_subclass_of($parameterClass->getName(), IFormDocument::class))) {
+                       throw new \InvalidArgumentException(
+                               "The processor function's first parameter must be an instance of '" . IFormDocument::class . "', instead " .
+                               ($parameterClass === null ? 'any' : "'" . $parameterClass->getName() . "'") . " parameter is expected."
+                       );
+               }
+               if (!$parameters[1]->isArray()) {
+                       throw new \InvalidArgumentException("The processor function's second parameter must be an array.");
+               }
+               
+               $this->processor = $processor;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function __invoke(IFormDocument $document, array $parameters) {
+               $parameters = call_user_func($this->processor, $document, $parameters);
+               
+               if (!is_array($parameters)) {
+                       throw new \UnexpectedValueException("Field data processor '{$this->id}' does not return an array.");
+               }
+               
+               return $parameters;
+       }
+}