From d4a91983106190afc161a8d7e42854da8ede570a Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 17 Sep 2015 14:42:02 +0200 Subject: [PATCH] Navigation: Only fail if there's really no chance to create the requested hierarchy refs #5600 --- library/Icinga/Web/Navigation/Navigation.php | 41 +++++++++++++++----- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/library/Icinga/Web/Navigation/Navigation.php b/library/Icinga/Web/Navigation/Navigation.php index 6c1b931b9..9cd3423a3 100644 --- a/library/Icinga/Web/Navigation/Navigation.php +++ b/library/Icinga/Web/Navigation/Navigation.php @@ -470,7 +470,7 @@ class Navigation implements ArrayAccess, Countable, IteratorAggregate throw new InvalidArgumentException('Argument $config must be an array or a instance of Traversable'); } - $flattened = $topLevel = array(); + $flattened = $orphans = $topLevel = array(); foreach ($config as $sectionName => $sectionConfig) { $parentName = $sectionConfig->parent; unset($sectionConfig->parent); @@ -482,17 +482,40 @@ class Navigation implements ArrayAccess, Countable, IteratorAggregate $flattened[$parentName]['children'][$sectionName] = $sectionConfig->toArray(); $flattened[$sectionName] = & $flattened[$parentName]['children'][$sectionName]; } else { - throw new ConfigurationError( - t( - 'Failed to add navigation item "%s". Parent "%s" not found. Make' - . ' sure that the parent is defined prior to its child(s).' - ), - $sectionName, - $parentName - ); + $orphans[$parentName][$sectionName] = $sectionConfig->toArray(); + $flattened[$sectionName] = & $orphans[$parentName][$sectionName]; } } + do { + $match = false; + foreach ($orphans as $parentName => $children) { + if (isset($flattened[$parentName])) { + if (isset($flattened[$parentName]['children'])) { + $flattened[$parentName]['children'] = array_merge( + $flattened[$parentName]['children'], + $children + ); + } else { + $flattened[$parentName]['children'] = $children; + } + + unset($orphans[$parentName]); + $match = true; + } + } + } while ($match && !empty($orphans)); + + if (! empty($orphans)) { + throw new ConfigurationError( + t( + 'Failed to fully parse navigation configuration. Ensure that' + . ' all referenced parents are existing navigation items: %s' + ), + join(', ', array_keys($orphans)) + ); + } + return static::fromArray($topLevel); }