Refactor MenuComposer to improve type safety and simplify local menu builder integration

This commit is contained in:
2025-09-29 15:03:05 +00:00
parent 4f51ef81ad
commit 3928b2cc7a
6 changed files with 132 additions and 100 deletions

View File

@@ -13,32 +13,30 @@ namespace Chill\MainBundle\Routing;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\Routing\RouteCollection;
use Knp\Menu\MenuItem;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This class permit to build menu from the routing information
* stored in each bundle.
*
* how to must come here FIXME
*/
class MenuComposer
final readonly class MenuComposer
{
private array $localMenuBuilders = [];
public function __construct(
private RouterInterface $router,
private FactoryInterface $menuFactory,
private TranslatorInterface $translator,
/**
* @var iterable<LocalMenuBuilderInterface>
*/
private iterable $localMenuBuilders,
) {}
private RouteCollection $routeCollection;
public function __construct(private readonly RouterInterface $router, private readonly FactoryInterface $menuFactory, private readonly TranslatorInterface $translator) {}
public function addLocalMenuBuilder(LocalMenuBuilderInterface $menuBuilder, $menuId)
public function getMenuFor($menuId, array $parameters = []): ItemInterface
{
$this->localMenuBuilders[$menuId][] = $menuBuilder;
}
public function getMenuFor($menuId, array $parameters = [])
{
$routes = $this->getRoutesFor($menuId, $parameters);
$routes = $this->getRoutesForInternal($menuId, $parameters);
/** @var MenuItem $menu */
$menu = $this->menuFactory->createItem($menuId);
// build menu from routes
@@ -55,10 +53,9 @@ class MenuComposer
]);
}
if ($this->hasLocalMenuBuilder($menuId)) {
foreach ($this->localMenuBuilders[$menuId] as $builder) {
/* @var $builder LocalMenuBuilderInterface */
$builder->buildMenu($menuId, $menu, $parameters['args']);
foreach ($this->localMenuBuilders as $builder) {
if (in_array($menuId, $builder::getMenuIds(), true)) {
$builder->buildMenu($menuId, $menu, $parameters);
}
}
@@ -71,12 +68,16 @@ class MenuComposer
* Return an array of routes added to $menuId,
* The array is aimed to build route with MenuTwig.
*
* @param string $menuId
* @param array $parameters see https://redmine.champs-libres.coop/issues/179
* @deprecated
*
* @return array
* @param array $parameters see https://redmine.champs-libres.coop/issues/179
*/
public function getRoutesFor($menuId, array $parameters = [])
public function getRoutesFor(string $menuId, array $parameters = []): array
{
return $this->getRoutesForInternal($menuId, $parameters);
}
private function getRoutesForInternal(string $menuId, array $parameters = []): array
{
$routes = [];
$routeCollection = $this->router->getRouteCollection();
@@ -108,22 +109,17 @@ class MenuComposer
* should be used, or `getRouteFor`. The method `getMenuFor` should be used
* if the result is true (it **does** exists at least one menu builder.
*
* @param string $menuId
* @deprecated
*/
public function hasLocalMenuBuilder($menuId): bool
public function hasLocalMenuBuilder(string $menuId): bool
{
return \array_key_exists($menuId, $this->localMenuBuilders);
}
foreach ($this->localMenuBuilders as $localMenuBuilder) {
if (in_array($menuId, $localMenuBuilder::getMenuIds(), true)) {
return true;
}
}
/**
* Set the route Collection
* This function is needed for testing purpose: routeCollection is not
* available as a service (RouterInterface is provided as a service and
* added to this class as paramater in __construct).
*/
public function setRouteCollection(RouteCollection $routeCollection)
{
$this->routeCollection = $routeCollection;
return false;
}
private function reorderMenu(ItemInterface $menu)