From 711805c058cef0625f6cee03f9f5ad29041eb5b3 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 22:33:59 -0600 Subject: [PATCH 1/5] Propagates styles from bottom up --- src/Builder/CliMenuBuilder.php | 34 +++++++++++++++++++---------- test/Builder/CliMenuBuilderTest.php | 2 +- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index fb7cbfad..da576df9 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -188,12 +188,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, $menu, @@ -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,28 @@ public function build() : CliMenu $this->style->setDisplaysExtra($this->itemsHaveExtra($this->menu->getItems())); } + if (!$this->subMenu) { + $this->propagateStyles($this->menu); + } + return $this->menu; } + + /** + * Pass styles from current menu to sub-menu + * only if sub-menu style has not be customized + */ + private function propagateStyles(CliMenu $menu) + { + foreach ($menu->getItems() as $item) { + if ($item instanceof MenuMenuItem) { + $subMenu = $item->getSubMenu(); + + !$subMenu->getStyle()->hasChangedFromDefaults() + && $subMenu->setStyle(clone $menu->getStyle()); + + $this->propagateStyles($subMenu); + } + } + } } diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 55df7f49..08d2c450 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -593,7 +593,7 @@ public function testSubMenuInheritsParentsStyle() : void ->build(); self::assertSame('green', $menu->getItems()[0]->getSubMenu()->getStyle()->getBg()); - self::assertSame($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle()); + self::assertEquals($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle()); } public function testSubMenuDoesNotInheritsParentsStyleWhenSubMenuStyleHasAlterations() : void From 3f6ae03eabd8ecfd497ad574b5dbaa8874855b02 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 22:46:09 -0600 Subject: [PATCH 2/5] Adds test for multi-nested menu --- test/Builder/CliMenuBuilderTest.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 08d2c450..233b10d6 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -587,13 +587,21 @@ public function testSubMenuInheritsParentsStyle() : void $menu = (new CliMenuBuilder($terminal)) ->setBackgroundColour('green') ->addSubMenu('My SubMenu', function (CliMenuBuilder $b) { - $b->addItem('Some Item', function () { + $b->addSubMenu('My SubSubMenu', function (CliMenuBuilder $b) { + $b->addItem('Some Item', function () { + }); }); }) ->build(); - self::assertSame('green', $menu->getItems()[0]->getSubMenu()->getStyle()->getBg()); - self::assertEquals($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle()); + $subMenu1 = $menu->getItems()[0]->getSubMenu(); + $subMenu2 = $subMenu1->getItems()[0]->getSubMenu(); + + self::assertSame('green', $subMenu1->getStyle()->getBg()); + self::assertEquals($menu->getStyle(), $subMenu1->getStyle()); + + self::assertSame('green', $subMenu2->getStyle()->getBg()); + self::assertEquals($menu->getStyle(), $subMenu2->getStyle()); } public function testSubMenuDoesNotInheritsParentsStyleWhenSubMenuStyleHasAlterations() : void From eede6bf6bfc20b0da762d1c81ccad988ee4f6112 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Thu, 19 Dec 2019 23:05:44 -0600 Subject: [PATCH 3/5] Adds test for multi-nested with custom style --- test/Builder/CliMenuBuilderTest.php | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 233b10d6..c0fb29b4 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -583,7 +583,7 @@ public function testSubMenuInheritsParentsStyle() : void ->expects($this->any()) ->method('getWidth') ->will($this->returnValue(200)); - + $menu = (new CliMenuBuilder($terminal)) ->setBackgroundColour('green') ->addSubMenu('My SubMenu', function (CliMenuBuilder $b) { @@ -594,7 +594,9 @@ public function testSubMenuInheritsParentsStyle() : void }) ->build(); + /** @var CliMenu $subMenu1 */ $subMenu1 = $menu->getItems()[0]->getSubMenu(); + /** @var CliMenu $subMenu2 */ $subMenu2 = $subMenu1->getItems()[0]->getSubMenu(); self::assertSame('green', $subMenu1->getStyle()->getBg()); @@ -604,6 +606,35 @@ public function testSubMenuInheritsParentsStyle() : void self::assertEquals($menu->getStyle(), $subMenu2->getStyle()); } + public function testSubMenuIgnoresParentsStyleIfCustomAndPassesToChildren() : 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->setBackgroundColour('yellow') + ->addSubMenu('My SubSubMenu', function (CliMenuBuilder $b) { + $b->addItem('Some Item', function () { + }); + }); + }) + ->build(); + + /** @var CliMenu $subMenu1 */ + $subMenu1 = $menu->getItems()[0]->getSubMenu(); + /** @var CliMenu $subMenu2 */ + $subMenu2 = $subMenu1->getItems()[0]->getSubMenu(); + + self::assertSame('green', $menu->getStyle()->getBg()); + self::assertSame('yellow', $subMenu1->getStyle()->getBg()); + self::assertSame('yellow', $subMenu2->getStyle()->getBg()); + } + public function testSubMenuDoesNotInheritsParentsStyleWhenSubMenuStyleHasAlterations() : void { $menu = (new CliMenuBuilder) From b57065d1ee8881b96703be1e1669f6d3b9d4fd53 Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Fri, 20 Dec 2019 00:22:59 -0600 Subject: [PATCH 4/5] Adds test for propagating styles to SplitItem + SubMenu --- src/Builder/CliMenuBuilder.php | 12 +++++++++-- test/Builder/CliMenuBuilderTest.php | 32 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index da576df9..3c38bbc2 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -555,9 +555,12 @@ public function build() : CliMenu * Pass styles from current menu to sub-menu * only if sub-menu style has not be customized */ - private function propagateStyles(CliMenu $menu) + private function propagateStyles(CliMenu $menu, array $items = []) { - foreach ($menu->getItems() as $item) { + $currentItems = !empty($items) ? $items : $menu->getItems(); + + foreach ($currentItems as $item) { + // Apply current style to children, if they are not customized if ($item instanceof MenuMenuItem) { $subMenu = $item->getSubMenu(); @@ -566,6 +569,11 @@ private function propagateStyles(CliMenu $menu) $this->propagateStyles($subMenu); } + + // Apply styles to SplitItem children using current $menu + if ($item instanceof SplitItem) { + $this->propagateStyles($menu, $item->getItems()); + } } } } diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index c0fb29b4..85bd8fc7 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -11,6 +11,7 @@ use PhpSchool\CliMenu\MenuItem\MenuMenuItem; use PhpSchool\CliMenu\MenuItem\RadioItem; use PhpSchool\CliMenu\MenuItem\SelectableItem; +use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\Terminal\Terminal; use PHPUnit\Framework\TestCase; @@ -606,6 +607,37 @@ public function testSubMenuInheritsParentsStyle() : void self::assertEquals($menu->getStyle(), $subMenu2->getStyle()); } + public function testSplitItemSubMenuInheritsParentsStyle() : void + { + $terminal = self::createMock(Terminal::class); + $terminal + ->expects($this->any()) + ->method('getWidth') + ->will($this->returnValue(200)); + + $menu = (new CliMenuBuilder($terminal)) + ->setBackgroundColour('green') + ->addSplitItem(function (SplitItemBuilder $b) { + $b + ->addItem('Item 1', function () {}) + ->addSubMenu('Submenu 1', function (CliMenuBuilder $b) { + $b->addItem('Item 2', function () {}); + }) + ; + }) + ->build(); + + /** @var SplitItem $splitItem */ + $splitItem = $menu->getItems()[0]; + /** @var SelectableItem $selectableItem1 */ + $selectableItem1 = $splitItem->getItems()[0]; + /** @var CliMenu $subMenu */ + $subMenu = $splitItem->getItems()[1]->getSubMenu(); + + self::assertSame('green', $subMenu->getStyle()->getBg()); + self::assertEquals($menu->getStyle(), $subMenu->getStyle()); + } + public function testSubMenuIgnoresParentsStyleIfCustomAndPassesToChildren() : void { $terminal = self::createMock(Terminal::class); From 62534772e241821b3e2f10d5552f417eb1bb92ca Mon Sep 17 00:00:00 2001 From: Juan Treminio Date: Fri, 20 Dec 2019 00:30:03 -0600 Subject: [PATCH 5/5] CS fix --- src/Builder/CliMenuBuilder.php | 5 +++-- test/Builder/CliMenuBuilderTest.php | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Builder/CliMenuBuilder.php b/src/Builder/CliMenuBuilder.php index 3c38bbc2..5edd7a4e 100644 --- a/src/Builder/CliMenuBuilder.php +++ b/src/Builder/CliMenuBuilder.php @@ -564,8 +564,9 @@ private function propagateStyles(CliMenu $menu, array $items = []) if ($item instanceof MenuMenuItem) { $subMenu = $item->getSubMenu(); - !$subMenu->getStyle()->hasChangedFromDefaults() - && $subMenu->setStyle(clone $menu->getStyle()); + if (!$subMenu->getStyle()->hasChangedFromDefaults()) { + $subMenu->setStyle(clone $menu->getStyle()); + } $this->propagateStyles($subMenu); } diff --git a/test/Builder/CliMenuBuilderTest.php b/test/Builder/CliMenuBuilderTest.php index 85bd8fc7..244d5a33 100644 --- a/test/Builder/CliMenuBuilderTest.php +++ b/test/Builder/CliMenuBuilderTest.php @@ -619,9 +619,11 @@ public function testSplitItemSubMenuInheritsParentsStyle() : void ->setBackgroundColour('green') ->addSplitItem(function (SplitItemBuilder $b) { $b - ->addItem('Item 1', function () {}) + ->addItem('Item 1', function () { + }) ->addSubMenu('Submenu 1', function (CliMenuBuilder $b) { - $b->addItem('Item 2', function () {}); + $b->addItem('Item 2', function () { + }); }) ; }) @@ -653,7 +655,7 @@ public function testSubMenuIgnoresParentsStyleIfCustomAndPassesToChildren() : vo ->addSubMenu('My SubSubMenu', function (CliMenuBuilder $b) { $b->addItem('Some Item', function () { }); - }); + }); }) ->build();