moduleTemplate->getDocHeaderComponent()->getButtonBar(); * * // Use pre-configured save button * $saveButton = $this->componentFactory->createSaveButton('editform'); * $buttonBar->addButton($saveButton, ButtonBar::BUTTON_POSITION_LEFT, 1); * * // Use pre-configured back button * $backButton = $this->componentFactory->createBackButton($returnUrl); * $buttonBar->addButton($backButton, ButtonBar::BUTTON_POSITION_LEFT, 2); * } * ``` * * Example - Creating custom buttons with ComponentFactory: * * ``` * public function __construct( * protected readonly ComponentFactory $componentFactory, * ) {} * * public function myAction(): ResponseInterface * { * $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); * * // Create custom link button * $customButton = $this->componentFactory->createLinkButton() * ->setHref('/custom-action') * ->setTitle('Custom Action') * ->setIcon($iconFactory->getIcon('actions-custom')); * $buttonBar->addButton($customButton, ButtonBar::BUTTON_POSITION_LEFT, 1); * } * ``` * * Example - Buttons with automatic positioning: * * ``` * // ShortcutButton implements PositionInterface and positions itself automatically * $shortcutButton = $this->componentFactory->createShortcutButton() * ->setRouteIdentifier('my_module') * ->setDisplayName('My Module'); * $buttonBar->addButton($shortcutButton); // Position and group are automatic * ``` * * Example - Dropdown button: * * ``` * $dropdownButton = $this->componentFactory->createDropDownButton() * ->setLabel('Actions') * ->setIcon($iconFactory->getIcon('actions-menu')); * * $item1 = $this->componentFactory->createDropDownItem() * ->setLabel('Edit') * ->setHref('/edit'); * $dropdownButton->addItem($item1); * * $item2 = $this->componentFactory->createDropDownItem() * ->setLabel('Delete') * ->setHref('/delete'); * $dropdownButton->addItem($item2); * * $buttonBar->addButton($dropdownButton, ButtonBar::BUTTON_POSITION_RIGHT, 1); * ``` * * @phpstan-type Buttons array>> */ #[Autoconfigure(public: true)] class ButtonBar { /** * Position constant for left side of the button bar */ public const BUTTON_POSITION_LEFT = 'left'; /** * Position constant for right side of the button bar */ public const BUTTON_POSITION_RIGHT = 'right'; /** * Internal array of all registered buttons * * @var Buttons */ protected array $buttons = []; public function __construct( protected readonly EventDispatcherInterface $eventDispatcher, ) {} /** * Add a new button * * Buttons implementing PositionInterface will automatically use their own * predefined position and group, ignoring the $buttonPosition and $buttonGroup * parameters. This ensures buttons like ShortcutButton always appear in their * designated location. * * @param ButtonInterface $button The Button Object to add * @param self::BUTTON_POSITION_* $buttonPosition Position of the button (left/right). Ignored if button implements PositionInterface. * @param int $buttonGroup Buttongroup of the button. Ignored if button implements PositionInterface. * * @throws \InvalidArgumentException In case a button is not valid */ public function addButton( ButtonInterface $button, string $buttonPosition = self::BUTTON_POSITION_LEFT, int $buttonGroup = 1 ): static { if (!$button->isValid()) { throw new \InvalidArgumentException('Button "' . $button->getType() . '" is not valid', 1441706370); } // Buttons implementing PositionInterface define their own position and group if ($button instanceof PositionInterface) { $buttonPosition = $button->getPosition(); $buttonGroup = $button->getGroup(); } // We make the button immutable here $this->buttons[$buttonPosition][$buttonGroup][] = clone $button; return $this; } /** * Returns an associative array of all buttons in the form of * ButtonPosition > ButtonGroup > Button */ public function getButtons(ServerRequestInterface $request): array { // here we need to call the sorting methods and stuff. foreach ($this->buttons as $position => $_) { ksort($this->buttons[$position]); } // Dispatch event for manipulating the docHeaderButtons $this->buttons = $this->eventDispatcher->dispatch(new ModifyButtonBarEvent($this->buttons, $this, $request))->getButtons(); return $this->buttons; } /** * Checks whether a button of the specified type has been added to the button bar. * * This is primarily used for backwards compatibility detection to prevent * duplicate automatic buttons when controllers manually add them. * * @param class-string $buttonClassName Fully qualified button class name * @return bool True if a button of this type exists, false otherwise */ public function hasButtonOfType(string $buttonClassName): bool { foreach ($this->buttons as $groups) { foreach ($groups as $groupButtons) { foreach ($groupButtons as $button) { if ($button instanceof $buttonClassName) { return true; } } } } return false; } }