From: Matthias Schmidt Date: Sat, 13 Jan 2018 17:37:17 +0000 (+0100) Subject: Add concept of form node availability for form builder X-Git-Tag: 5.2.0_Alpha_1~857 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f663fffe8ce56047ff93b799594ddef30d3ceec9;p=GitHub%2FWoltLab%2FWCF.git Add concept of form node availability for form builder See #2509 --- diff --git a/wcfsetup/install/files/acp/templates/__form.tpl b/wcfsetup/install/files/acp/templates/__form.tpl index 7d869e3bb2..a8ad558bb9 100644 --- a/wcfsetup/install/files/acp/templates/__form.tpl +++ b/wcfsetup/install/files/acp/templates/__form.tpl @@ -1,6 +1,8 @@
getClasses()|empty} class="{implode from=$form->getClasses() item='class'}{$class}{/implode}"{/if}{foreach from=$form->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}> {foreach from=$form item='child'} - {@$child->getHtml()} + {if $child->isAvailable()} + {@$child->getHtml()} + {/if} {/foreach}
diff --git a/wcfsetup/install/files/acp/templates/__formContainerChildren.tpl b/wcfsetup/install/files/acp/templates/__formContainerChildren.tpl index f9c9a8c5e0..67486e3906 100644 --- a/wcfsetup/install/files/acp/templates/__formContainerChildren.tpl +++ b/wcfsetup/install/files/acp/templates/__formContainerChildren.tpl @@ -1,3 +1,5 @@ {foreach from=$container item='child'} - {@$child->getHtml()} + {if $child->isAvailable()} + {@$child->getHtml()} + {/if} {/foreach} \ No newline at end of file diff --git a/wcfsetup/install/files/acp/templates/__tabMenuFormContainer.tpl b/wcfsetup/install/files/acp/templates/__tabMenuFormContainer.tpl index 752775dc54..f8f3e15b80 100644 --- a/wcfsetup/install/files/acp/templates/__tabMenuFormContainer.tpl +++ b/wcfsetup/install/files/acp/templates/__tabMenuFormContainer.tpl @@ -2,8 +2,10 @@ diff --git a/wcfsetup/install/files/acp/templates/__tabTabMenuFormContainer.tpl b/wcfsetup/install/files/acp/templates/__tabTabMenuFormContainer.tpl index 3f84fca1ec..a181463413 100644 --- a/wcfsetup/install/files/acp/templates/__tabTabMenuFormContainer.tpl +++ b/wcfsetup/install/files/acp/templates/__tabTabMenuFormContainer.tpl @@ -2,7 +2,10 @@ 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 5773b6cd8d..ba0c6ab2ee 100644 --- a/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/FormDocument.class.php @@ -166,7 +166,7 @@ class FormDocument implements IFormDocument { public function loadValuesFromObject(IStorableObject $object) { /** @var IFormNode $node */ foreach ($this->getIterator() as $node) { - if ($node instanceof IFormField) { + if ($node instanceof IFormField && $node->isAvailable()) { $node->loadValueFromObject($object); } } diff --git a/wcfsetup/install/files/lib/system/form/builder/IFormNode.class.php b/wcfsetup/install/files/lib/system/form/builder/IFormNode.class.php index ca6725ff6d..59e1ec818e 100644 --- a/wcfsetup/install/files/lib/system/form/builder/IFormNode.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/IFormNode.class.php @@ -48,6 +48,30 @@ interface IFormNode { */ public function attribute($name, $value = null); + /** + * Sets if this node is available and returns this node. + * + * By default, every node is available. This methods makes it easier to create forms + * that contains node that are only avaiable if certain options have specific values + * or the active user has specific permissions, for example. Furthermore, fields + * themselves are also able to mark themselves as unavailable, for example, a selection + * field without any options. A `IFormContainer` is automatically unavailable if it + * contains no available children. + * + * Unavailable fields produce no output, their value is not read, they are not validated + * and they are not checked for save values. + * + * Note: Form field dependencies manage dynamic availability of form nodes based on + * form field values while this method manages static availability that is independent + * of form field values and only depends on external factors. + * + * @param bool $available determines if node is available + * @return static this node + * + * @throws \InvalidArgumentException if the given value is no bool + */ + public function available($available = true); + /** * Returns `true` if the node's dependencies are met and returns `false` otherwise. * @@ -175,6 +199,17 @@ interface IFormNode { */ public function id($id); + /** + * Returns `true` if this node is available and returns `false` otherwise. + * + * If the node's availability has not been explicitly set, `true` is returned. + * + * @return bool + * + * @see IFormNode::available() + */ + public function isAvailable(); + /** * Is called once after all nodes have been added to the document this node belongs to. * diff --git a/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php b/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php index 2b92600a02..f327143710 100644 --- a/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php @@ -18,6 +18,12 @@ trait TFormNode { */ protected $__attributes = []; + /** + * `true` if this node is available and `false` otherwise + * @var bool + */ + protected $__available = true; + /** * CSS classes of this node * @var string[] @@ -108,6 +114,38 @@ trait TFormNode { return $this; } + /** + * Sets if this node is available and returns this node. + * + * By default, every node is available. This methods makes it easier to create forms + * that contains node that are only avaiable if certain options have specific values + * or the active user has specific permissions, for example. Furthermore, fields + * themselves are also able to mark themselves as unavailable, for example, a selection + * field without any options. A `IFormContainer` is automatically unavailable if it + * contains no available children. + * + * Unavailable fields produce no output, their value is not read, they are not validated + * and they are not checked for save values. + * + * Note: Form field dependencies manage dynamic availability of form nodes based on + * form field values while this method manages static availability that is independent + * of form field values and only depends on external factors. + * + * @param bool $available determines if node is available + * @return static this node + * + * @throws \InvalidArgumentException if the given value is no bool + */ + public function available($available = true) { + if (!is_bool($available)) { + throw new \InvalidArgumentException("Given value is no bool, " . gettype($available) . " given."); + } + + $this->__available = $available; + + return $this; + } + /** * Returns `true` if the node's dependencies are met and returns `false` otherwise. * @@ -307,6 +345,30 @@ trait TFormNode { return $this; } + /** + * Returns `true` if this node is available and returns `false` otherwise. + * + * If the node's own availability has not been explicitly set, it is assumed to be `true`. + * + * @return bool + * + * @see IFormNode::available() + */ + public function isAvailable() { + if ($this->__available && $this instanceof IFormParentNode) { + /** @var IFormChildNode $child */ + foreach ($this as $child) { + if ($child->isAvailable()) { + return true; + } + } + + return false; + } + + return $this->__available; + } + /** * Is called once after all nodes have been added to the document this node belongs to. * diff --git a/wcfsetup/install/files/lib/system/form/builder/TFormParentNode.class.php b/wcfsetup/install/files/lib/system/form/builder/TFormParentNode.class.php index 9dbc5cf845..2e42372116 100644 --- a/wcfsetup/install/files/lib/system/form/builder/TFormParentNode.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/TFormParentNode.class.php @@ -246,12 +246,14 @@ trait TFormParentNode { * @return static this node */ public function readValues() { - foreach ($this->children() as $child) { - if ($child instanceof IFormParentNode) { - $child->readValues(); - } - else if ($child instanceof IFormField && !$child->isImmutable()) { - $child->readValue(); + if ($this->isAvailable()) { + foreach ($this->children() as $child) { + if ($child instanceof IFormParentNode) { + $child->readValues(); + } + else if ($child instanceof IFormField && $child->isAvailable() && !$child->isImmutable()) { + $child->readValue(); + } } } @@ -282,11 +284,11 @@ trait TFormParentNode { * nodes are valid. A `IFormField` object is valid if its value is valid. */ public function validate() { - if ($this->checkDependencies()) { + if ($this->isAvailable() && $this->checkDependencies()) { foreach ($this->children() as $child) { // call `checkDependencies()` on form fields here so that their validate // method does not have to do it - if ($child instanceof IFormField && !$child->checkDependencies()) { + if ($child instanceof IFormField && $child->isAvailable() && !$child->checkDependencies()) { continue; } diff --git a/wcfsetup/install/files/lib/system/form/builder/field/TSelectionFormField.class.php b/wcfsetup/install/files/lib/system/form/builder/field/TSelectionFormField.class.php index b90e1b5828..ade337f3e5 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/TSelectionFormField.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/TSelectionFormField.class.php @@ -36,6 +36,20 @@ trait TSelectionFormField { return $this->__options; } + /** + * Returns `true` if this node is available and returns `false` otherwise. + * + * If the node's availability has not been explicitly set, `true` is returned. + * + * @return bool + * + * @see IFormNode::available() + */ + public function isAvailable() { + // selections without any possible values are not available + return !empty($this->possibleValues) && parent::isAvailable(); + } + /** * Sets the possible options of this selection and returns this field. * diff --git a/wcfsetup/install/files/lib/system/form/builder/field/data/DefaultFormFieldDataProcessor.class.php b/wcfsetup/install/files/lib/system/form/builder/field/data/DefaultFormFieldDataProcessor.class.php index c4300abe19..d3129a7d00 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/data/DefaultFormFieldDataProcessor.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/data/DefaultFormFieldDataProcessor.class.php @@ -41,7 +41,7 @@ class DefaultFormFieldDataProcessor implements IFormFieldDataProcessor { $this->getData($childNode, $data); } } - else if ($node instanceof IFormField && $node->hasSaveValue()) { + else if ($node instanceof IFormField && $node->isAvailable() && $node->hasSaveValue()) { $data[$node->getId()] = $node->getSaveValue(); } }