Fix duplicate node id validation
authorMatthias Schmidt <gravatronics@live.com>
Mon, 28 May 2018 17:56:31 +0000 (19:56 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Mon, 28 May 2018 17:56:31 +0000 (19:56 +0200)
See #2509

wcfsetup/install/files/lib/acp/form/DevtoolsFormBuilderTestForm.class.php
wcfsetup/install/files/lib/system/form/builder/TFormParentNode.class.php
wcfsetup/install/files/lib/system/form/builder/container/FormContainer.class.php

index 63056faba3b1cbe523fe7327896d781f0b737ab0..973146853b0e6d3ed633081d38b8c963dabe7f74 100644 (file)
@@ -181,10 +181,12 @@ class DevtoolsFormBuilderTestForm extends AbstractForm {
                                        TabFormContainer::create('tab2')
                                                ->label('Tab 2')
                                                ->appendChildren([
-                                                       SimpleAclFormField::create('objectAccess')
-                                                               ->label('Object can be accessed'),
-                                                       UsernameFormField::create('newUsername')
-                                                               ->label('A new username')
+                                                       FormContainer::create('tab2Contents')->appendChildren([
+                                                               SimpleAclFormField::create('objectAccess')
+                                                                       ->label('Object can be accessed'),
+                                                               UsernameFormField::create('newUsername')
+                                                                       ->label('A new username')
+                                                       ])
                                                ])
                                ])
                ]);
index 9f01c5c39721b142113f4fdece4e6eeb68b68505..567b4180ed7a1642d9d4553e8eedf164f791c7f4 100644 (file)
@@ -34,6 +34,8 @@ trait TFormParentNode {
         * @throws      \InvalidArgumentException               if the given child node cannot be appended
         */
        public function appendChild(IFormChildNode $child): IFormParentNode {
+               $this->validateChild($child);
+               
                $this->__children[] = $child;
                
                $child->parent($this);
@@ -316,8 +318,19 @@ trait TFormParentNode {
         * @throws      \InvalidArgumentException                       if given node cannot be added as a child
         */
        public function validateChild(IFormChildNode $child) {
-               if ($this->getDocument()->contains($child->getId())) {
-                       throw new \InvalidArgumentException("Cannot append node '{$child->getId()}' to node '{$this->getId()}' because a node with id '{$child->getId()}' already exists in the form.");
+               // check if a node with same id as the given node already exists
+               if ($this->contains($child->getId())) {
+                       throw new \InvalidArgumentException("Cannot append node '{$child->getId()}' to node '{$this->getId()}' because a node with id '{$child->getId()}' already exists.");
+               }
+               
+               // check all child nodes of the given node for duplicate node ids
+               if ($child instanceof IFormParentNode) {
+                       /** @var IFormNode $thisChild */
+                       foreach ($child->getIterator() as $grandChild) {
+                               if ($grandChild instanceof IFormParentNode && $this->contains($grandChild->getId())) {
+                                       throw new \InvalidArgumentException("Cannot append node '{$child->getId()}' to node '{$this->getId()}' because '{$child->getId()}' contains a node with id '{$grandChild->getId()}' that is already used by another node.");
+                               }
+                       }
                }
        }
 }
index f9c1f59ab623384110b6293ffab657ddb17e5751..9f80e911100c0e25c1a82af6c7422b583aa21551 100644 (file)
@@ -45,7 +45,7 @@ class FormContainer implements IFormContainer {
        public function validateChild(IFormChildNode $child) {
                $this->defaultValidateChild($child);
                
-               if ($this instanceof ITabFormMenuContainer) {
+               if ($this instanceof ITabMenuFormContainer) {
                        if (!($child instanceof ITabFormContainer)) {
                                throw new \InvalidArgumentException("Cannot append non-tab container ".get_class($child)."('{$child->getId()}') to tab menu container '{$this->getId()}'");
                        }