diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index f8f165ff..5e6e4dd9 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -187,12 +187,6 @@ public function addSubMenu(string $text, \Closure $callback) : self $menu = $builder->build(); $menu->setParent($this->menu); - - //we apply the parent theme if nothing was changed - //if no styles were changed in this sub-menu - if (!$menu->getStyle()->hasChangedFromDefaults()) { - $menu->setStyle($this->menu->getStyle()); - } $this->menu->addItem($item = new MenuMenuItem( $text, @@ -210,12 +204,6 @@ public function addSubMenuFromBuilder(string $text, CliMenuBuilder $builder) : s $menu = $builder->build(); $menu->setParent($this->menu); - //we apply the parent theme if nothing was changed - //if no styles were changed in this sub-menu - if (!$menu->getStyle()->hasChangedFromDefaults()) { - $menu->setStyle($this->menu->getStyle()); - } - $this->menu->addItem($item = new MenuMenuItem( $text, $menu, @@ -556,6 +544,31 @@ public function build() : CliMenu $this->style->setDisplaysExtra($this->itemsHaveExtra($this->menu->getItems())); } + if (!$this->subMenu) { + $this->propagateStyles($this->menu->getItems()); + } + return $this->menu; } + + private function propagateStyles(array $items) : void + { + $menuItems = array_filter($items, function (MenuItemInterface $menuItem) { + return $menuItem instanceof MenuMenuItem; + }); + + $changedMenus = array_filter($menuItems, function (MenuMenuItem $menuItem) { + return !$menuItem->getSubMenu() + ->getStyle() + ->hasChangedFromDefaults(); + }); + + array_walk($changedMenus, function (MenuMenuItem $menuItem) { + $menuItem->getSubMenu()->setStyle( + $this->menu->getStyle() + ); + + $this->propagateStyles($menuItem->getSubMenu()->getItems()); + }); + } } diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 93a82f03..6b658da9 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -596,6 +596,33 @@ public function testSubMenuInheritsParentsStyle() : void self::assertSame($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle()); } + public function testNestedSubMenuInheritsParentsStyle() : void + { + $terminal = self::createMock(Terminal::class); + $terminal + ->expects($this->any()) + ->method('getWidth') + ->will($this->returnValue(200)); + + $menu = (new CliMenuBuilder($terminal)) + ->setBackgroundColour('green') + ->addSubMenu('My SubMenu', function (CliMenuBuilder $b) { + $b->addSubMenu('Nested submenu', function (CliMenuBuilder $b) { + $b->addItem('Nested item', function () { + }); + })->addItem('Some Item', function () { + }); + }) + ->build(); + + self::assertSame('green', $menu->getItems()[0]->getSubMenu()->getStyle()->getBg()); + self::assertSame($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle()); + self::assertSame( + $menu->getStyle(), + $menu->getItems()[0]->getSubMenu()->getItems()[0]->getSubMenu()->getStyle() + ); + } + public function testSubMenuDoesNotInheritsParentsStyleWhenSubMenuStyleHasAlterations() : void { $menu = (new CliMenuBuilder)