From 996224f54ad9fa79e81c63c6abb074c0bd030291 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 17 Sep 2015 15:53:12 +0200 Subject: [PATCH] NavigationConfigForm: Do not allow to configure circular parent child relations refs #5600 --- .../forms/Navigation/NavigationConfigForm.php | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/application/forms/Navigation/NavigationConfigForm.php b/application/forms/Navigation/NavigationConfigForm.php index a5b01e490..f2bb0be70 100644 --- a/application/forms/Navigation/NavigationConfigForm.php +++ b/application/forms/Navigation/NavigationConfigForm.php @@ -194,6 +194,8 @@ class NavigationConfigForm extends ConfigForm } } + $children = $this->itemToLoad ? $this->getFlattenedChildren($this->itemToLoad) : array(); + $names = array(); if ($shared) { foreach ($this->getShareConfig() as $sectionName => $sectionConfig) { @@ -201,22 +203,51 @@ class NavigationConfigForm extends ConfigForm $sectionName !== $this->itemToLoad && $sectionConfig->type === $type && $sectionConfig->owner === $this->getUser()->getUsername() + && !in_array($sectionName, $children, true) ) { $names[] = $sectionName; } } } else { foreach ($this->getUserConfig() as $sectionName => $sectionConfig) { - if ($sectionName !== $this->itemToLoad && $sectionConfig->type === $type) { + if ( + $sectionName !== $this->itemToLoad + && $sectionConfig->type === $type + && !in_array($sectionName, $children, true) + ) { $names[] = $sectionName; } } } - // TODO: Ensure that it's not possible to produce circular references return $names; } + /** + * Recursively return all children of the given navigation item + * + * @param string $name + * + * @return array + */ + protected function getFlattenedChildren($name) + { + $config = $this->getConfigForItem($name); + if ($config === null) { + return array(); + } + + $children = array(); + foreach ($config as $sectionName => $sectionConfig) { + if ($sectionConfig->parent === $name) { + $children[] = $sectionName; + $children = array_merge($children, $this->getFlattenedChildren($sectionName)); + } + } + + return $children; + } + /** * Populate the form with the given navigation item's config *