From 9ee226c827922d32384e8369ac3f85bbbe987de8 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Tue, 1 May 2018 16:42:53 +1100 Subject: [PATCH 1/9] Add Split Item --- src/CliMenu.php | 68 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/CliMenu.php b/src/CliMenu.php index 99d2bcc3..e5477e93 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -12,6 +12,7 @@ use PhpSchool\CliMenu\Input\Text; use PhpSchool\CliMenu\MenuItem\LineBreakItem; use PhpSchool\CliMenu\MenuItem\MenuItemInterface; +use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\CliMenu\Dialogue\Confirm; use PhpSchool\CliMenu\Dialogue\Flash; @@ -171,6 +172,8 @@ private function display() : void 'j' => InputCharacter::DOWN, "\r" => InputCharacter::ENTER, ' ' => InputCharacter::ENTER, + 'l' => 'LEFT', + 'm' => 'RIGHT', ]); while ($this->isOpen() && $char = $reader->readCharacter()) { @@ -181,6 +184,8 @@ private function display() : void switch ($char->getControl()) { case InputCharacter::UP: case InputCharacter::DOWN: + case 'LEFT': + case 'RIGHT': $this->moveSelection($char->getControl()); $this->draw(); break; @@ -197,25 +202,56 @@ private function display() : void protected function moveSelection(string $direction) : void { do { - $itemKeys = array_keys($this->items); - - $direction === 'UP' - ? $this->selectedItem-- - : $this->selectedItem++; - - if (!array_key_exists($this->selectedItem, $this->items)) { - $this->selectedItem = $direction === 'UP' - ? end($itemKeys) - : reset($itemKeys); - } elseif ($this->getSelectedItem()->canSelect()) { - return; + if ($direction === 'UP' || $direction === 'DOWN') { + $itemKeys = array_keys($this->items); + + $direction === 'UP' + ? $this->selectedItem-- + : $this->selectedItem++; + + if (!array_key_exists($this->selectedItem, $this->items)) { + $this->selectedItem = $direction === 'UP' + ? end($itemKeys) + : reset($itemKeys); + } elseif ($this->getSelectedItem()->canSelect()) { + return; + } + } else { + $item = $this->getSelectedItem(true); + if (!$item instanceof SplitItem) { + return; + } + + $itemKeys = array_keys($item->getItems()); + $selectedItemIndex = $item->getSelectedItemIndex(); + $direction === 'LEFT' + ? $selectedItemIndex-- + : $selectedItemIndex++; + $item->setSelectedItemIndex($selectedItemIndex); + if (!array_key_exists($selectedItemIndex, $item->getItems())) { + $selectedItemIndex = $direction === 'LEFT' + ? end($itemKeys) + : reset($itemKeys); + $item->setSelectedItemIndex($selectedItemIndex); + } elseif ($item->getItems()[$item->getSelectedItemIndex()]->canSelect()) { + return; + } } } while (!$this->getSelectedItem()->canSelect()); } - public function getSelectedItem() : MenuItemInterface + public function getSelectedItem(bool $oneLevelDeep = false) : MenuItemInterface { - return $this->items[$this->selectedItem]; + if ($oneLevelDeep) { + return $this->items[$this->selectedItem]; + } else { + $item = $this->items[$this->selectedItem]; + if ($item instanceof SplitItem) { + $item = $item->getItems()[$item->getSelectedItemIndex()]; + } + + return $item; + } } /** @@ -286,6 +322,10 @@ protected function draw() : void protected function drawMenuItem(MenuItemInterface $item, bool $selected = false) : array { $rows = $item->getRows($this->style, $selected); + + if ($item instanceof SplitItem) { + $selected = false; + } $setColour = $selected ? $this->style->getSelectedSetCode() From 1ebbfcfa1e0f75e913001ef6302475480c384412 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Tue, 1 May 2018 16:45:54 +1100 Subject: [PATCH 2/9] Add Split Item --- src/CliMenuBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CliMenuBuilder.php b/src/CliMenuBuilder.php index 6a0c09a9..479c8fa5 100644 --- a/src/CliMenuBuilder.php +++ b/src/CliMenuBuilder.php @@ -9,6 +9,7 @@ use PhpSchool\CliMenu\MenuItem\MenuItemInterface; use PhpSchool\CliMenu\MenuItem\MenuMenuItem; use PhpSchool\CliMenu\MenuItem\SelectableItem; +use PhpSchool\CliMenu\MenuItem\SplitItem; use PhpSchool\CliMenu\MenuItem\StaticItem; use PhpSchool\CliMenu\Terminal\TerminalFactory; use Assert\Assertion; From 2d6f51627201c4ed0d92a2e7665b9e687c3ba033 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Tue, 1 May 2018 16:48:34 +1100 Subject: [PATCH 3/9] Create SplitItem.php --- src/MenuItem/SplitItem.php | 180 +++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/MenuItem/SplitItem.php diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php new file mode 100644 index 00000000..36162ad5 --- /dev/null +++ b/src/MenuItem/SplitItem.php @@ -0,0 +1,180 @@ + + */ +class SplitItem implements MenuItemInterface +{ + /** + * @var string + */ + private $text; + + /** + * @var array + */ + private $items; + + /** + * @var int + */ + private $selectedItemIndex = null; + + /** + * @var int + */ + private $margin = 2; + + + public function __construct(string $text, array $items) + { + $this->text = $text; + $this->items = $items; + } + + /** + * The output text for the item + */ + public function getRows(MenuStyle $style, bool $selected = false) : array + { + $numberOfItems = count($this->items); + + if (!$selected) { + $this->selectedItemIndex = null; + } else { + if (empty($this->selectedItemIndex)) { + $this->selectedItemIndex = 0; + } + } + + $length = $style->getDisplaysExtra() + ? floor(($style->getContentWidth() - mb_strlen($style->getItemExtra()) + 2) / $numberOfItems) - $this->margin + : floor($style->getContentWidth() / $numberOfItems) - $this->margin; + $missingLength = $style->getContentWidth() % $numberOfItems; + + $lines = 0; + $cells = []; + foreach ($this->items as $index => $item) { + $marker = sprintf("%s ", $style->getMarker($index === $this->selectedItemIndex)); + $content = StringUtil::wordwrap( + sprintf('%s%s', $marker, $item->getText()), + $length + ); + $cell = array_map(function ($row) use ($index, $length, $style) { + $row = $row . str_repeat(' ', $length - strlen($row)); + if ($index === $this->selectedItemIndex) { + $row = $style->getSelectedSetCode() . $row . $style->getSelectedUnsetCode(); + } else { + $row = $style->getUnselectedSetCode() . $row . $style->getUnselectedUnsetCode(); + } + $row .= $style->getUnselectedSetCode() . str_repeat(' ', $this->margin); + return $row; + }, explode("\n", $content)); + $lineCount = count($cell); + if ($lineCount > $lines) { + $lines = $lineCount; + } + $cells[] = $cell; + } + + $rows = []; + for ($i = 0; $i < $lines; $i++) { + $row = ""; + foreach ($cells as $cell) { + if (isset($cell[$i])) { + $row .= $cell[$i]; + } else { + $row .= str_repeat(' ', $length); + } + } + if ($missingLength) { + $row .= str_repeat(' ', $missingLength); + } + $rows[] = $row; + } + + return $rows; + } + + /** + * + */ + public function setSelectedItemIndex(int $index) : void + { + $this->selectedItemIndex = $index; + } + + /** + * + */ + public function getSelectedItemIndex() : int + { + if (empty($this->selectedItemIndex)) { + return 0; + } + return $this->selectedItemIndex; + } + + /** + * + */ + public function getItems() : array + { + return $this->items; + } + + /** + * Can the item be selected + */ + public function canSelect() : bool + { + return true; + } + + /** + * Execute the items callable if required + */ + public function getSelectAction() : ?callable + { + return null; + } + + /** + * Whether or not the menu item is showing the menustyle extra value + */ + public function showsItemExtra() : bool + { + return false; + } + + /** + * Enable showing item extra + */ + public function showItemExtra() : void + { + //noop + } + + /** + * Disable showing item extra + */ + public function hideItemExtra() : void + { + //noop + } + + /** + * Return the raw string of text + */ + public function getText() : string + { + return $this->text; + } +} From b6613742ab03debc09f284d45d9b8de3cb31785f Mon Sep 17 00:00:00 2001 From: Lynesth Date: Tue, 1 May 2018 17:06:25 +1100 Subject: [PATCH 4/9] Fix PSR2 + non-nullable int --- src/MenuItem/SplitItem.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 36162ad5..3cd49050 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -24,8 +24,9 @@ class SplitItem implements MenuItemInterface /** * @var int + * -1 means no item selected */ - private $selectedItemIndex = null; + private $selectedItemIndex = -1; /** * @var int @@ -47,9 +48,9 @@ public function getRows(MenuStyle $style, bool $selected = false) : array $numberOfItems = count($this->items); if (!$selected) { - $this->selectedItemIndex = null; + $this->selectedItemIndex = -1; } else { - if (empty($this->selectedItemIndex)) { + if ($this->selectedItemIndex === -1) { $this->selectedItemIndex = 0; } } @@ -64,9 +65,9 @@ public function getRows(MenuStyle $style, bool $selected = false) : array foreach ($this->items as $index => $item) { $marker = sprintf("%s ", $style->getMarker($index === $this->selectedItemIndex)); $content = StringUtil::wordwrap( - sprintf('%s%s', $marker, $item->getText()), - $length - ); + sprintf('%s%s', $marker, $item->getText()), + $length + ); $cell = array_map(function ($row) use ($index, $length, $style) { $row = $row . str_repeat(' ', $length - strlen($row)); if ($index === $this->selectedItemIndex) { @@ -116,7 +117,7 @@ public function setSelectedItemIndex(int $index) : void */ public function getSelectedItemIndex() : int { - if (empty($this->selectedItemIndex)) { + if ($this->selectedItemIndex === -1) { return 0; } return $this->selectedItemIndex; From fc48628438416d660c84e26ea23535a590aa9a70 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 11 May 2018 21:49:00 +1100 Subject: [PATCH 5/9] Integration with CliMenuBuilder --- src/CliMenu.php | 5 +- src/CliMenuBuilder.php | 11 ++++ src/MenuItem/SplitItem.php | 129 ++++++++++++++++++++++++++----------- 3 files changed, 106 insertions(+), 39 deletions(-) diff --git a/src/CliMenu.php b/src/CliMenu.php index 2661233e..cccdb731 100644 --- a/src/CliMenu.php +++ b/src/CliMenu.php @@ -257,8 +257,8 @@ private function display() : void switch ($char->getControl()) { case InputCharacter::UP: case InputCharacter::DOWN: - case 'LEFT': - case 'RIGHT': + case InputCharacter::LEFT: + case InputCharacter::RIGHT: $this->moveSelection($char->getControl()); $this->draw(); break; @@ -301,6 +301,7 @@ protected function moveSelection(string $direction) : void ? $selectedItemIndex-- : $selectedItemIndex++; $item->setSelectedItemIndex($selectedItemIndex); + if (!array_key_exists($selectedItemIndex, $item->getItems())) { $selectedItemIndex = $direction === 'LEFT' ? end($itemKeys) diff --git a/src/CliMenuBuilder.php b/src/CliMenuBuilder.php index 0e9bcb2a..1e5f9b22 100644 --- a/src/CliMenuBuilder.php +++ b/src/CliMenuBuilder.php @@ -162,6 +162,17 @@ public function addSubMenu(string $id, CliMenuBuilder $subMenuBuilder = null) : return $this; } + /** + * Add a split item + */ + public function addSplitItem() : SplitItem + { + $splitItem = new SplitItem($this); + $this->addMenuItem($splitItem); + + return $splitItem; + } + /** * Disable a submenu * diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 3cd49050..0d606da7 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -4,6 +4,7 @@ use Assert\Assertion; use PhpSchool\CliMenu\CliMenu; +use PhpSchool\CliMenu\CliMenuBuilder; use PhpSchool\CliMenu\MenuStyle; use PhpSchool\CliMenu\Util\StringUtil; @@ -13,20 +14,24 @@ class SplitItem implements MenuItemInterface { /** - * @var string + * @var array */ - private $text; + private $items; /** - * @var array + * @var CliMenuBuilder */ - private $items; + private $parentBuilder; /** * @var int - * -1 means no item selected */ - private $selectedItemIndex = -1; + private $selectedItemIndex; + + /** + * @var bool + */ + private $canBeSelected = true; /** * @var int @@ -34,10 +39,53 @@ class SplitItem implements MenuItemInterface private $margin = 2; - public function __construct(string $text, array $items) + public function __construct(CliMenuBuilder $builder, array $items = []) { - $this->text = $text; - $this->items = $items; + $this->parentBuilder = $builder; + $this->items = $items; + + $this->setDefaultSelectedItem(); + } + + /** + * Select default item + */ + private function setDefaultSelectedItem() { + foreach ($this->items as $index => $item) { + if ($item->canSelect()) { + $this->canBeSelected = true; + $this->selectedItemIndex = $index; + return; + } + } + + $this->canBeSelected = false; + $this->selectedItemIndex = null; + } + + public function addItem( + string $text, + callable $itemCallable, + bool $showItemExtra = false, + bool $disabled = false + ) : self { + $this->items[] = new SelectableItem($text, $itemCallable, $showItemExtra, $disabled); + $this->setDefaultSelectedItem(); + + return $this; + } + + public function addStaticItem(string $text) : self + { + $this->items[] = new StaticItem($text); + $this->setDefaultSelectedItem(); + + return $this; + } + + public function end() : CliMenuBuilder + { + return $this->parentBuilder; } /** @@ -48,11 +96,7 @@ public function getRows(MenuStyle $style, bool $selected = false) : array $numberOfItems = count($this->items); if (!$selected) { - $this->selectedItemIndex = -1; - } else { - if ($this->selectedItemIndex === -1) { - $this->selectedItemIndex = 0; - } + $this->setDefaultSelectedItem(); } $length = $style->getDisplaysExtra() @@ -63,20 +107,27 @@ public function getRows(MenuStyle $style, bool $selected = false) : array $lines = 0; $cells = []; foreach ($this->items as $index => $item) { - $marker = sprintf("%s ", $style->getMarker($index === $this->selectedItemIndex)); + $isSelected = $selected && $index === $this->selectedItemIndex; + $marker = sprintf("%s ", $style->getMarker($isSelected)); $content = StringUtil::wordwrap( sprintf('%s%s', $marker, $item->getText()), $length ); - $cell = array_map(function ($row) use ($index, $length, $style) { - $row = $row . str_repeat(' ', $length - strlen($row)); - if ($index === $this->selectedItemIndex) { - $row = $style->getSelectedSetCode() . $row . $style->getSelectedUnsetCode(); - } else { - $row = $style->getUnselectedSetCode() . $row . $style->getUnselectedUnsetCode(); - } - $row .= $style->getUnselectedSetCode() . str_repeat(' ', $this->margin); - return $row; + $cell = array_map(function ($row) use ($index, $length, $style, $isSelected) { + $invertedColoursSetCode = $isSelected + ? $style->getInvertedColoursSetCode() + : ''; + $invertedColoursUnsetCode = $isSelected + ? $style->getInvertedColoursUnsetCode() + : ''; + + return sprintf("%s%s%s%s%s", + $invertedColoursSetCode, + $row, + str_repeat(' ', $length - mb_strlen($row)), + $invertedColoursUnsetCode, + str_repeat(' ', $this->margin) + ); }, explode("\n", $content)); $lineCount = count($cell); if ($lineCount > $lines) { @@ -88,6 +139,9 @@ public function getRows(MenuStyle $style, bool $selected = false) : array $rows = []; for ($i = 0; $i < $lines; $i++) { $row = ""; + if ($i > 0) { + $row .= str_repeat(' ', 2); + } foreach ($cells as $cell) { if (isset($cell[$i])) { $row .= $cell[$i]; @@ -104,28 +158,24 @@ public function getRows(MenuStyle $style, bool $selected = false) : array return $rows; } - /** - * - */ public function setSelectedItemIndex(int $index) : void { $this->selectedItemIndex = $index; } - /** - * - */ public function getSelectedItemIndex() : int { - if ($this->selectedItemIndex === -1) { + if ($this->selectedItemIndex === null) { return 0; } return $this->selectedItemIndex; } - - /** - * - */ + + public function getSelectedItem() : MenuItem + { + return $this->items[$this->selectedItemIndex]; + } + public function getItems() : array { return $this->items; @@ -133,10 +183,11 @@ public function getItems() : array /** * Can the item be selected + * Not really in this case but that's the trick */ public function canSelect() : bool { - return true; + return $this->canBeSelected; } /** @@ -176,6 +227,10 @@ public function hideItemExtra() : void */ public function getText() : string { - return $this->text; + $text = []; + foreach ($this->items as $item) { + $text[] = $item->getText(); + } + return explode(' - ', $text); } } From 31f134f9c0d98fb58eda0eda62903a7cb62e8a37 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 11 May 2018 22:01:01 +1100 Subject: [PATCH 6/9] cs --- src/MenuItem/SplitItem.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 0d606da7..e5263b06 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -50,7 +50,8 @@ public function __construct(CliMenuBuilder $builder, array $items = []) /** * Select default item */ - private function setDefaultSelectedItem() { + private function setDefaultSelectedItem() + { foreach ($this->items as $index => $item) { if ($item->canSelect()) { $this->canBeSelected = true; @@ -121,7 +122,8 @@ public function getRows(MenuStyle $style, bool $selected = false) : array ? $style->getInvertedColoursUnsetCode() : ''; - return sprintf("%s%s%s%s%s", + return sprintf( + "%s%s%s%s%s", $invertedColoursSetCode, $row, str_repeat(' ', $length - mb_strlen($row)), From 0483240af76f9a236d59a90c316b10b1d75e6f0d Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 12 May 2018 02:24:38 +1100 Subject: [PATCH 7/9] Add submenus to split items --- src/CliMenuBuilder.php | 21 +++++++++++++++++++-- src/MenuItem/SplitItem.php | 28 ++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/CliMenuBuilder.php b/src/CliMenuBuilder.php index 1e5f9b22..3d8c3b6e 100644 --- a/src/CliMenuBuilder.php +++ b/src/CliMenuBuilder.php @@ -32,6 +32,8 @@ class CliMenuBuilder */ private $parent; + private $previousBuilder = null; + /** * @var self[] */ @@ -82,9 +84,10 @@ class CliMenuBuilder */ private $disabled = false; - public function __construct(CliMenuBuilder $parent = null) + public function __construct(CliMenuBuilder $parent = null, $previousBuilder = null) { $this->parent = $parent; + $this->previousBuilder = $previousBuilder; $this->terminal = $this->parent !== null ? $this->parent->getTerminal() : TerminalFactory::fromSystem(); @@ -162,6 +165,16 @@ public function addSubMenu(string $id, CliMenuBuilder $subMenuBuilder = null) : return $this; } + /** + * Injects a submenu directly (without going through the builder + */ + public function injectSubMenu(string $id, CliMenu $subMenu) : CliMenuBuilder + { + $this->subMenus[$id] = $subMenu; + + return $this; + } + /** * Add a split item */ @@ -423,8 +436,12 @@ private function buildStyle() : MenuStyle * * @throws RuntimeException */ - public function end() : CliMenuBuilder + public function end() { + if (null !== $this->previousBuilder) { + return $this->previousBuilder; + } + if (null === $this->parent) { throw new RuntimeException('No parent builder to return to'); } diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index e5263b06..ee77472e 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -71,7 +71,6 @@ public function addItem( bool $disabled = false ) : self { $this->items[] = new SelectableItem($text, $itemCallable, $showItemExtra, $disabled); - $this->setDefaultSelectedItem(); return $this; } @@ -79,13 +78,38 @@ public function addItem( public function addStaticItem(string $text) : self { $this->items[] = new StaticItem($text); - $this->setDefaultSelectedItem(); return $this; } + public function addSubMenu(string $id, CliMenuBuilder $subMenuBuilder = null) : CliMenuBuilder + { + if (null === $subMenuBuilder) { + $subMenuBuilder = new CliMenuBuilder($this->parentBuilder, $this); + } + + $this->items[] = $id; + $this->subMenuBuilders[$id] = $subMenuBuilder; + + return $subMenuBuilder; + } + public function end() : CliMenuBuilder { + $this->items = array_map(function ($item) { + if (!is_string($item) || empty($this->subMenuBuilders[$item])) { + return $item; + } + + $subMenuBuilder = $this->subMenuBuilders[$item]; + $subMenu = $subMenuBuilder->build(); + $this->parentBuilder->injectSubMenu($item, $subMenu); + + return new MenuMenuItem($item, $subMenu, $subMenuBuilder->isMenuDisabled()); + }, $this->items); + + $this->setDefaultSelectedItem(); + return $this->parentBuilder; } From 021ec8d16ebec9804aa73b6987834cda6407fa28 Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 12 May 2018 02:41:12 +1100 Subject: [PATCH 8/9] Adding convenience function addMenuItem() --- src/MenuItem/SplitItem.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index ee77472e..63fe3c6c 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -38,6 +38,15 @@ class SplitItem implements MenuItemInterface */ private $margin = 2; + /** + * @var array + */ + private $blacklistedItems = [ + "AsciiArtItem", + "LineBreakItem", + "SplitItem", + ]; + public function __construct(CliMenuBuilder $builder, array $items = []) { @@ -64,6 +73,19 @@ private function setDefaultSelectedItem() $this->selectedItemIndex = null; } + public function addMenuItem(MenuItemInterface $item) : self + { + foreach ($this->blacklistedItems as $bl) { + if ($item instanceof $bl) { + throw new \InvalidArgumentException("Cannot add a $bl to a SplitItem"); + } + } + + $this->items[] = $item; + + return $this; + } + public function addItem( string $text, callable $itemCallable, From e465a27157075b41c4b648855ead87948cdf095c Mon Sep 17 00:00:00 2001 From: Lynesth Date: Sat, 12 May 2018 02:54:13 +1100 Subject: [PATCH 9/9] More useful functions --- src/MenuItem/SplitItem.php | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/MenuItem/SplitItem.php b/src/MenuItem/SplitItem.php index 63fe3c6c..f9ea9c8c 100644 --- a/src/MenuItem/SplitItem.php +++ b/src/MenuItem/SplitItem.php @@ -42,9 +42,9 @@ class SplitItem implements MenuItemInterface * @var array */ private $blacklistedItems = [ - "AsciiArtItem", - "LineBreakItem", - "SplitItem", + '\PhpSchool\CliMenu\MenuItem\AsciiArtItem', + '\PhpSchool\CliMenu\MenuItem\LineBreakItem', + '\PhpSchool\CliMenu\MenuItem\SplitItem', ]; @@ -62,7 +62,7 @@ public function __construct(CliMenuBuilder $builder, array $items = []) private function setDefaultSelectedItem() { foreach ($this->items as $index => $item) { - if ($item->canSelect()) { + if ($item instanceof MenuItemInterface && $item->canSelect()) { $this->canBeSelected = true; $this->selectedItemIndex = $index; return; @@ -83,6 +83,25 @@ public function addMenuItem(MenuItemInterface $item) : self $this->items[] = $item; + $this->setDefaultSelectedItem(); + + return $this; + } + + public function addMenuItems(array $items) : self + { + foreach ($items as $item) { + $this->addMenuItem($item); + } + + return $this; + } + + public function setItems(array $items) : self + { + $this->items = []; + $this->addMenuItems($item); + return $this; }