Skip to content

Commit da5a0b7

Browse files
authored
Merge pull request #210 from jtreminio/feature/propagate-styles
Propagates styles from bottom up
2 parents c72b588 + 6253477 commit da5a0b7

File tree

2 files changed

+108
-16
lines changed

2 files changed

+108
-16
lines changed

src/Builder/CliMenuBuilder.php

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,6 @@ public function addSubMenu(string $text, \Closure $callback) : self
188188
$menu = $builder->build();
189189
$menu->setParent($this->menu);
190190

191-
//we apply the parent theme if nothing was changed
192-
//if no styles were changed in this sub-menu
193-
if (!$menu->getStyle()->hasChangedFromDefaults()) {
194-
$menu->setStyle($this->menu->getStyle());
195-
}
196-
197191
$this->menu->addItem($item = new MenuMenuItem(
198192
$text,
199193
$menu,
@@ -210,12 +204,6 @@ public function addSubMenuFromBuilder(string $text, CliMenuBuilder $builder) : s
210204
$menu = $builder->build();
211205
$menu->setParent($this->menu);
212206

213-
//we apply the parent theme if nothing was changed
214-
//if no styles were changed in this sub-menu
215-
if (!$menu->getStyle()->hasChangedFromDefaults()) {
216-
$menu->setStyle($this->menu->getStyle());
217-
}
218-
219207
$this->menu->addItem($item = new MenuMenuItem(
220208
$text,
221209
$menu,
@@ -556,6 +544,37 @@ public function build() : CliMenu
556544
$this->style->setDisplaysExtra($this->itemsHaveExtra($this->menu->getItems()));
557545
}
558546

547+
if (!$this->subMenu) {
548+
$this->propagateStyles($this->menu);
549+
}
550+
559551
return $this->menu;
560552
}
553+
554+
/**
555+
* Pass styles from current menu to sub-menu
556+
* only if sub-menu style has not be customized
557+
*/
558+
private function propagateStyles(CliMenu $menu, array $items = [])
559+
{
560+
$currentItems = !empty($items) ? $items : $menu->getItems();
561+
562+
foreach ($currentItems as $item) {
563+
// Apply current style to children, if they are not customized
564+
if ($item instanceof MenuMenuItem) {
565+
$subMenu = $item->getSubMenu();
566+
567+
if (!$subMenu->getStyle()->hasChangedFromDefaults()) {
568+
$subMenu->setStyle(clone $menu->getStyle());
569+
}
570+
571+
$this->propagateStyles($subMenu);
572+
}
573+
574+
// Apply styles to SplitItem children using current $menu
575+
if ($item instanceof SplitItem) {
576+
$this->propagateStyles($menu, $item->getItems());
577+
}
578+
}
579+
}
561580
}

test/Builder/CliMenuBuilderTest.php

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PhpSchool\CliMenu\MenuItem\MenuMenuItem;
1212
use PhpSchool\CliMenu\MenuItem\RadioItem;
1313
use PhpSchool\CliMenu\MenuItem\SelectableItem;
14+
use PhpSchool\CliMenu\MenuItem\SplitItem;
1415
use PhpSchool\CliMenu\MenuItem\StaticItem;
1516
use PhpSchool\Terminal\Terminal;
1617
use PHPUnit\Framework\TestCase;
@@ -583,17 +584,89 @@ public function testSubMenuInheritsParentsStyle() : void
583584
->expects($this->any())
584585
->method('getWidth')
585586
->will($this->returnValue(200));
586-
587+
587588
$menu = (new CliMenuBuilder($terminal))
588589
->setBackgroundColour('green')
589590
->addSubMenu('My SubMenu', function (CliMenuBuilder $b) {
590-
$b->addItem('Some Item', function () {
591+
$b->addSubMenu('My SubSubMenu', function (CliMenuBuilder $b) {
592+
$b->addItem('Some Item', function () {
593+
});
591594
});
592595
})
593596
->build();
594597

595-
self::assertSame('green', $menu->getItems()[0]->getSubMenu()->getStyle()->getBg());
596-
self::assertSame($menu->getStyle(), $menu->getItems()[0]->getSubMenu()->getStyle());
598+
/** @var CliMenu $subMenu1 */
599+
$subMenu1 = $menu->getItems()[0]->getSubMenu();
600+
/** @var CliMenu $subMenu2 */
601+
$subMenu2 = $subMenu1->getItems()[0]->getSubMenu();
602+
603+
self::assertSame('green', $subMenu1->getStyle()->getBg());
604+
self::assertEquals($menu->getStyle(), $subMenu1->getStyle());
605+
606+
self::assertSame('green', $subMenu2->getStyle()->getBg());
607+
self::assertEquals($menu->getStyle(), $subMenu2->getStyle());
608+
}
609+
610+
public function testSplitItemSubMenuInheritsParentsStyle() : void
611+
{
612+
$terminal = self::createMock(Terminal::class);
613+
$terminal
614+
->expects($this->any())
615+
->method('getWidth')
616+
->will($this->returnValue(200));
617+
618+
$menu = (new CliMenuBuilder($terminal))
619+
->setBackgroundColour('green')
620+
->addSplitItem(function (SplitItemBuilder $b) {
621+
$b
622+
->addItem('Item 1', function () {
623+
})
624+
->addSubMenu('Submenu 1', function (CliMenuBuilder $b) {
625+
$b->addItem('Item 2', function () {
626+
});
627+
})
628+
;
629+
})
630+
->build();
631+
632+
/** @var SplitItem $splitItem */
633+
$splitItem = $menu->getItems()[0];
634+
/** @var SelectableItem $selectableItem1 */
635+
$selectableItem1 = $splitItem->getItems()[0];
636+
/** @var CliMenu $subMenu */
637+
$subMenu = $splitItem->getItems()[1]->getSubMenu();
638+
639+
self::assertSame('green', $subMenu->getStyle()->getBg());
640+
self::assertEquals($menu->getStyle(), $subMenu->getStyle());
641+
}
642+
643+
public function testSubMenuIgnoresParentsStyleIfCustomAndPassesToChildren() : void
644+
{
645+
$terminal = self::createMock(Terminal::class);
646+
$terminal
647+
->expects($this->any())
648+
->method('getWidth')
649+
->will($this->returnValue(200));
650+
651+
$menu = (new CliMenuBuilder($terminal))
652+
->setBackgroundColour('green')
653+
->addSubMenu('My SubMenu', function (CliMenuBuilder $b) {
654+
$b->setBackgroundColour('yellow')
655+
->addSubMenu('My SubSubMenu', function (CliMenuBuilder $b) {
656+
$b->addItem('Some Item', function () {
657+
});
658+
});
659+
})
660+
->build();
661+
662+
/** @var CliMenu $subMenu1 */
663+
$subMenu1 = $menu->getItems()[0]->getSubMenu();
664+
/** @var CliMenu $subMenu2 */
665+
$subMenu2 = $subMenu1->getItems()[0]->getSubMenu();
666+
667+
self::assertSame('green', $menu->getStyle()->getBg());
668+
self::assertSame('yellow', $subMenu1->getStyle()->getBg());
669+
self::assertSame('yellow', $subMenu2->getStyle()->getBg());
597670
}
598671

599672
public function testSubMenuDoesNotInheritsParentsStyleWhenSubMenuStyleHasAlterations() : void

0 commit comments

Comments
 (0)