diff --git a/lib/classes/ActionMenu.php b/lib/classes/ActionMenu.php index f7ec8881bb520405b287373507b7c2b6d1a12f1b..6fc016a2e7c2946b7fcd08b5c7e17ff6f1ef1c1d 100644 --- a/lib/classes/ActionMenu.php +++ b/lib/classes/ActionMenu.php @@ -11,6 +11,9 @@ class ActionMenu const TEMPLATE_FILE_SINGLE = 'shared/action-menu-single.php'; const TEMPLATE_FILE_MULTIPLE = 'shared/action-menu.php'; + const RENDERING_MODE_ICONS = 'icons'; + const RENDERING_MODE_MENU = 'menu'; + /** * Returns an instance. * @@ -32,6 +35,10 @@ class ActionMenu */ protected $context = ''; + /** + * @var string|null $rendering_mode The forced rendering mode + */ + protected $rendering_mode = null; /** * Private constructur. @@ -248,10 +255,10 @@ class ActionMenu return ''; } - $template_file = count($this->actions) <= Config::get()->ACTION_MENU_THRESHOLD + $template_file = $this->getRenderingMode() === self::RENDERING_MODE_ICONS ? self::TEMPLATE_FILE_SINGLE : self::TEMPLATE_FILE_MULTIPLE; - +; $template = $GLOBALS['template_factory']->open($template_file); $template->actions = array_map(function ($action) { $disabled = isset($action['attributes']['disabled']) @@ -287,7 +294,6 @@ class ActionMenu return null; } - /** * Sets the context for the menu. * @@ -302,6 +308,47 @@ class ActionMenu return $this; } + /** + * Forces an explicit rendering mode. + * + * @param string|null $mode The desired rendering mode or null for automatic detection + * @return ActionMenu The action menu instance to allow chaining + * @throws Exception + */ + public function setRenderingMode(?string $mode): ActionMenu + { + if ( + $mode !== null + && $mode !== self::RENDERING_MODE_ICONS + && $mode !== self::RENDERING_MODE_MENU + ) { + throw new Exception("Invalid rendering mode '{$mode}'"); + } + + $this->rendering_mode = $mode; + + return $this; + } + + /** + * Returns the rendering mode for this action menu. This is set by either + * calling setRenderingMode or automatically determined by the configured + * threshold. + * + * @return string + */ + public function getRenderingMode(): string + { + $rendering_mode = $this->rendering_mode; + + if ($rendering_mode === null) { + $rendering_mode = count($this->actions) <= Config::get()->ACTION_MENU_THRESHOLD + ? self::RENDERING_MODE_ICONS + : self::RENDERING_MODE_MENU; + } + + return $rendering_mode; + } /** * Generates the title of the action menu, including its context, if the context has been set. diff --git a/tests/unit/lib/classes/ActionMenuTest.php b/tests/unit/lib/classes/ActionMenuTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ece2c4e8b4d467ee9edd9e588d7de86b965801b8 --- /dev/null +++ b/tests/unit/lib/classes/ActionMenuTest.php @@ -0,0 +1,60 @@ +<?php +/** + * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> + * @since Stud.IP 5.4 + */ +class ActionMenuTest extends \Codeception\Test\Unit +{ + public function setup(): void + { + Config::set(new Config(['ACTION_MENU_THRESHOLD' => 1])); + } + + public function testClassShouldExist(): void + { + $this->assertTrue(class_exists(ActionMenu::class)); + } + + /** + * @covers ActionMenu::get + */ + public function testInstanceGeneration(): void + { + $actionmenu = ActionMenu::get(); + + $this->assertInstanceOf(ActionMenu::class, $actionmenu); + $this->assertNotSame($actionmenu, ActionMenu::get()); + } + + public function testThreshold(): void + { + $actionmenu = ActionMenu::get(); + + $this->assertEquals(ActionMenu::RENDERING_MODE_ICONS, $actionmenu->getRenderingMode()); + + $actionmenu->addLink('#1', 'foo'); + $this->assertEquals(ActionMenu::RENDERING_MODE_ICONS, $actionmenu->getRenderingMode()); + + $actionmenu->addLink('#2', 'bar'); + $this->assertEquals(ActionMenu::RENDERING_MODE_MENU, $actionmenu->getRenderingMode()); + } + + /** + * @covers ActionMenu::setRenderingMode + * @covers ActionMenu::getRenderingMode + */ + public function testForcingOfRenderingMode(): void + { + $actionmenu = ActionMenu::get(); + $this->assertEquals(ActionMenu::RENDERING_MODE_ICONS, $actionmenu->getRenderingMode()); + + $actionmenu->setRenderingMode(ActionMenu::RENDERING_MODE_ICONS); + $this->assertEquals(ActionMenu::RENDERING_MODE_ICONS, $actionmenu->getRenderingMode()); + + $actionmenu->setRenderingMode(ActionMenu::RENDERING_MODE_MENU); + $this->assertEquals(ActionMenu::RENDERING_MODE_MENU, $actionmenu->getRenderingMode()); + + $actionmenu->setRenderingMode(null); + $this->assertEquals(ActionMenu::RENDERING_MODE_ICONS, $actionmenu->getRenderingMode()); + } +}