Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
80.56% covered (warning)
80.56%
29 / 36
64.52% covered (warning)
64.52%
20 / 31
30.56% covered (danger)
30.56%
11 / 36
54.55% covered (warning)
54.55%
6 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
MenuTwig
80.56% covered (warning)
80.56%
29 / 36
64.52% covered (warning)
64.52%
20 / 31
30.56% covered (danger)
30.56%
11 / 36
54.55% covered (warning)
54.55%
6 / 11
153.96
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFunctions
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 newItem
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addItem
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
50.00% covered (danger)
50.00%
2 / 4
100.00% covered (success)
100.00%
1 / 1
4.12
 getItem
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUrl
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 isMenuItemActive
66.67% covered (warning)
66.67%
6 / 9
50.00% covered (danger)
50.00%
7 / 14
13.64% covered (danger)
13.64%
3 / 22
0.00% covered (danger)
0.00%
0 / 1
38.56
 isUrlMenuItemActive
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getMenuItems
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMenuSubItems
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMenuOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace App\Menu;
4
5use Symfony\Component\HttpFoundation\Request;
6use Symfony\Component\HttpFoundation\RequestStack;
7use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
8use Symfony\Component\Routing\Router;
9use Symfony\Component\Routing\RouterInterface;
10use Twig\Extension\AbstractExtension;
11use Twig\TwigFunction;
12
13class MenuTwig extends AbstractExtension
14{
15    /**
16     * @var array<array<array<MenuItem>>>
17     */
18    public array $menu = [];
19    public UrlGeneratorInterface $urlGenerator;
20    public ?Request $request;
21    public string $activeUri;
22
23    public function __construct(RouterInterface $router, RequestStack $requestStack)
24    {
25        /** @var Router $r */
26        $r = $router;
27        $this->urlGenerator = $r->getGenerator();
28        $this->request = $requestStack->getCurrentRequest();
29    }
30
31    public function getFunctions(): array
32    {
33        return [
34            new TwigFunction('getMenuItems', [$this, 'getMenuItems']),
35            new TwigFunction('getMenuSubItems', [$this, 'getMenuSubItems']),
36            new TwigFunction('getMenuOptions', [$this, 'getMenuOptions']),
37            new TwigFunction('isMenuItemActive', [$this, 'isMenuItemActive']),
38            new TwigFunction('isUrlMenuItemActive', [$this, 'isUrlMenuItemActive']),
39            new TwigFunction('addMenuItem', [$this, 'addItem']),
40            new TwigFunction('newMenuItem', [$this, 'newItem']),
41        ];
42    }
43
44    /**
45     * @param array<array<mixed>>|null $routeParams
46     * @param array<array<mixed>>|null $options
47     * @param MenuItem[]|null          $subItems
48     */
49    public function newItem(
50        string $id,
51        ?string $label,
52        ?string $route,
53        ?array $routeParams = [],
54        ?array $options = [],
55        ?array $subItems = [],
56    ): MenuItem {
57        return new MenuItem($id, $label, $route, $routeParams, $options, $subItems);
58    }
59
60    public function addItem(string $menuName, MenuItem $item): MenuTwig
61    {
62        $item->url = $this->getUrl($item);
63
64        if ($item->subItems) {
65            foreach ($item->subItems as $subItem) {
66                $subItem->url = $this->getUrl($subItem);
67            }
68        }
69        $this->menu[$menuName]['items'][$item->label] = $item;
70
71        return $this;
72    }
73
74    public function getItem(string $menuName, string $label): MenuItem|bool
75    {
76        return $this->menu[$menuName]['items'][$label] ?? false;
77    }
78
79    public function getUrl(MenuItem $item): ?string
80    {
81        if ($item->route) {
82            return $this->urlGenerator->generate($item->route, $item->routeParams ?? []);
83        }
84
85        /** @var ?string */
86        return $item->options['url'] ?? null;
87    }
88
89    public function isMenuItemActive(MenuItem $item): bool
90    {
91        $activeRoute = $this->request?->get('_route');
92        if ($item->route && $activeRoute == $item->route) {
93            return true;
94        }
95        $routes = $item->options['activeRoutes'] ?? false;
96        if ($routes && is_iterable($routes)) {
97            foreach ($routes as $route) {
98                if ($activeRoute == $route) {
99                    return true;
100                }
101            }
102        }
103
104        return false;
105    }
106
107    public function isUrlMenuItemActive(MenuItem $item): bool
108    {
109        return $item->url === $this->request?->getRequestUri();
110    }
111
112    /**
113     * @return MenuItem[]
114     */
115    public function getMenuItems(string $nom): array
116    {
117        return $this->menu[$nom]['items'] ?? [];
118    }
119
120    /**
121     * @return MenuItem[]|null
122     */
123    public function getMenuSubItems(MenuItem $item): ?array
124    {
125        return $item->subItems ?? [];
126    }
127
128    /**
129     * @return array<mixed>
130     */
131    public function getMenuOptions(string $nom): array
132    {
133        return $this->menu[$nom]['options'] ?? [];
134    }
135}

Branches

Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

MenuTwig->__construct
23    public function __construct(RouterInterface $router, RequestStack $requestStack)
24    {
25        /** @var Router $r */
26        $r = $router;
27        $this->urlGenerator = $r->getGenerator();
28        $this->request = $requestStack->getCurrentRequest();
29    }
MenuTwig->addItem
60    public function addItem(string $menuName, MenuItem $item): MenuTwig
61    {
62        $item->url = $this->getUrl($item);
63
64        if ($item->subItems) {
65            foreach ($item->subItems as $subItem) {
65            foreach ($item->subItems as $subItem) {
65            foreach ($item->subItems as $subItem) {
66                $subItem->url = $this->getUrl($subItem);
65            foreach ($item->subItems as $subItem) {
66                $subItem->url = $this->getUrl($subItem);
67            }
68        }
69        $this->menu[$menuName]['items'][$item->label] = $item;
69        $this->menu[$menuName]['items'][$item->label] = $item;
70
71        return $this;
72    }
MenuTwig->getFunctions
34            new TwigFunction('getMenuItems', [$this, 'getMenuItems']),
35            new TwigFunction('getMenuSubItems', [$this, 'getMenuSubItems']),
36            new TwigFunction('getMenuOptions', [$this, 'getMenuOptions']),
37            new TwigFunction('isMenuItemActive', [$this, 'isMenuItemActive']),
38            new TwigFunction('isUrlMenuItemActive', [$this, 'isUrlMenuItemActive']),
39            new TwigFunction('addMenuItem', [$this, 'addItem']),
40            new TwigFunction('newMenuItem', [$this, 'newItem']),
41        ];
42    }
MenuTwig->getItem
74    public function getItem(string $menuName, string $label): MenuItem|bool
75    {
76        return $this->menu[$menuName]['items'][$label] ?? false;
77    }
MenuTwig->getMenuItems
115    public function getMenuItems(string $nom): array
116    {
117        return $this->menu[$nom]['items'] ?? [];
118    }
MenuTwig->getMenuOptions
131    public function getMenuOptions(string $nom): array
132    {
133        return $this->menu[$nom]['options'] ?? [];
134    }
MenuTwig->getMenuSubItems
123    public function getMenuSubItems(MenuItem $item): ?array
124    {
125        return $item->subItems ?? [];
126    }
MenuTwig->getUrl
79    public function getUrl(MenuItem $item): ?string
80    {
81        if ($item->route) {
82            return $this->urlGenerator->generate($item->route, $item->routeParams ?? []);
86        return $item->options['url'] ?? null;
87    }
MenuTwig->isMenuItemActive
89    public function isMenuItemActive(MenuItem $item): bool
90    {
91        $activeRoute = $this->request?->get('_route');
92        if ($item->route && $activeRoute == $item->route) {
92        if ($item->route && $activeRoute == $item->route) {
92        if ($item->route && $activeRoute == $item->route) {
93            return true;
95        $routes = $item->options['activeRoutes'] ?? false;
96        if ($routes && is_iterable($routes)) {
96        if ($routes && is_iterable($routes)) {
96        if ($routes && is_iterable($routes)) {
97            foreach ($routes as $route) {
97            foreach ($routes as $route) {
98                if ($activeRoute == $route) {
99                    return true;
97            foreach ($routes as $route) {
97            foreach ($routes as $route) {
98                if ($activeRoute == $route) {
99                    return true;
100                }
101            }
102        }
103
104        return false;
104        return false;
105    }
MenuTwig->isUrlMenuItemActive
107    public function isUrlMenuItemActive(MenuItem $item): bool
108    {
109        return $item->url === $this->request?->getRequestUri();
110    }
MenuTwig->newItem
49    public function newItem(
50        string $id,
51        ?string $label,
52        ?string $route,
53        ?array $routeParams = [],
54        ?array $options = [],
55        ?array $subItems = [],
56    ): MenuItem {
57        return new MenuItem($id, $label, $route, $routeParams, $options, $subItems);
58    }