From cfd7dca5ec421140058bb3555583c06c3ac800f4 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sat, 22 Jun 2024 11:16:54 +0200 Subject: [PATCH] mvc: partially fix container field cloning, closes https://github.com/opnsense/core/issues/7521 While cloning model fields, the identifier for these new fields should also be set, which is currently being arranged in the ArrayField->add() method. This commit makes sure we set the identifiers for one level below the array field type, which is good enough for current implementations, eventually this should be a recursive action or needs a way to push the identifiers directly on clone. re-arrange the code a bit as well to remove the need for the $new_record array. --- .../OPNsense/Base/FieldTypes/ArrayField.php | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php index fa43656ca..ddc697a16 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php +++ b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php @@ -118,8 +118,17 @@ class ArrayField extends BaseField */ public function add() { - $new_record = array(); + $nodeUUID = $this->generateUUID(); + $container_node = $this->newContainerField($this->__reference . "." . $nodeUUID, $this->internalXMLTagName); + + $template_ref = $this->internalTemplateNode->__reference; foreach ($this->internalTemplateNode->iterateItems() as $key => $node) { + $new_node = clone $node; + $new_node->setInternalReference($container_node->__reference . "." . $key); + $new_node->applyDefault(); + $new_node->setChanged(); + $container_node->addChildNode($key, $new_node); + if ($node->isContainer()) { foreach ($node->iterateRecursiveItems() as $subnode) { if (is_a($subnode, "OPNsense\\Base\\FieldTypes\\ArrayField")) { @@ -127,18 +136,19 @@ class ArrayField extends BaseField throw new \Exception("Unsupported copy, Array doesn't support nesting."); } } - } - $new_record[$key] = clone $node; - } - $nodeUUID = $this->generateUUID(); - $container_node = $this->newContainerField($this->__reference . "." . $nodeUUID, $this->internalXMLTagName); - foreach ($new_record as $key => $node) { - // initialize field with new internal id and defined default value - $node->setInternalReference($container_node->__reference . "." . $key); - $node->applyDefault(); - $node->setChanged(); - $container_node->addChildNode($key, $node); + /** + * XXX: incomplete, only supports one nesting level of container fields. In the long run we probably + * should refactor the add() function to push identifiers differently. + */ + foreach ($node->iterateItems() as $subkey => $subnode) { + $new_subnode = clone $subnode; + $new_subnode->setInternalReference($new_node->__reference . "." . $subkey); + $new_subnode->applyDefault(); + $new_subnode->setChanged(); + $new_node->addChildNode($subkey, $new_subnode); + } + } } // make sure we have a UUID on repeating child items