mirror of
				https://github.com/kevinveenbirkenbach/infinito.git
				synced 2025-10-31 01:09:41 +00:00 
			
		
		
		
	Refactored menues
This commit is contained in:
		| @@ -20,16 +20,6 @@ services: | ||||
|         factory: ['@app.menu_builder', 'userTopbar'] | ||||
|         tags: | ||||
|             - { name: knp_menu.menu, alias: userTopbar } | ||||
|     app.menu.source: | ||||
|         class: Knp\Menu\MenuItem | ||||
|         factory: ['@app.menu_builder', 'sourceNavbar'] | ||||
|         tags: | ||||
|             - { name: knp_menu.menu, alias: sourceNavbar } | ||||
|     app.menu.node: | ||||
|         class: Knp\Menu\MenuItem | ||||
|         factory: ['@app.menu_builder', 'nodeSubbar'] | ||||
|         tags: | ||||
|             - { name: knp_menu.menu, alias: nodeSubbar } | ||||
|     # makes classes in src/ available to be used as services | ||||
|     # this creates a service per class whose id is the fully-qualified class name | ||||
|     Infinito\: | ||||
|   | ||||
| @@ -16,10 +16,6 @@ final class MenuEventType extends AbstractEnumType | ||||
| { | ||||
|     public const USER = 'app.menu.topbar.user'; | ||||
|  | ||||
|     public const SOURCE = 'app.menu.subbar.source'; | ||||
|  | ||||
|     public const NODE = 'app.menu.subbar.node'; | ||||
|  | ||||
|     /** | ||||
|      * May this will be used in the future. | ||||
|      * | ||||
|   | ||||
| @@ -11,12 +11,24 @@ use Fresh\DoctrineEnumBundle\DBAL\Types\AbstractEnumType; | ||||
|  */ | ||||
| final class RESTResponseType extends AbstractEnumType | ||||
| { | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     public const JSON = 'json'; | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     public const HTML = 'html'; | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     public const XML = 'xml'; | ||||
|  | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
|     protected static $choices = [ | ||||
|         self::JSON => 'json', | ||||
|         self::HTML => 'html', | ||||
|   | ||||
| @@ -31,26 +31,6 @@ class Menu | ||||
|         $this->factory = $factory; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RequestStack $request | ||||
|      * | ||||
|      * @return ItemInterface | ||||
|      */ | ||||
|     public function sourceNavbar(RequestStack $request): ItemInterface | ||||
|     { | ||||
|         return $this->createMenu(MenuEventType::SOURCE, $request); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RequestStack $request | ||||
|      * | ||||
|      * @return ItemInterface | ||||
|      */ | ||||
|     public function nodeSubbar(RequestStack $request): ItemInterface | ||||
|     { | ||||
|         return $this->createMenu(MenuEventType::NODE, $request); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RequestStack $request | ||||
|      * | ||||
|   | ||||
| @@ -6,6 +6,9 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; | ||||
| use Knp\Menu\ItemInterface; | ||||
| use Symfony\Component\EventDispatcher\Event; | ||||
| use Symfony\Component\Translation\TranslatorInterface; | ||||
| use Infinito\DBAL\Types\RESTResponseType; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use FOS\RestBundle\Request\ParameterBag; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
| @@ -15,19 +18,21 @@ abstract class AbstractEntityMenuSubscriber implements EventSubscriberInterface | ||||
|     /** | ||||
|      * @var TranslatorInterface | ||||
|      */ | ||||
|     private $translator; | ||||
|  | ||||
|     const FORMAT_TYPES = [ | ||||
|         'html', | ||||
|         'json', | ||||
|         'xml', | ||||
|     ]; | ||||
|     protected $translator; | ||||
|  | ||||
|     /** | ||||
|      * @param TranslatorInterface $translator | ||||
|      */ | ||||
|     public function __construct(TranslatorInterface $translator) | ||||
|     { | ||||
|         $this->translator = $translator; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param ItemInterface $menu | ||||
|      * @param Event         $event | ||||
|      * @param string        $route | ||||
|      */ | ||||
|     protected function generateShowDropdown(ItemInterface $menu, Event $event, string $route): void | ||||
|     { | ||||
|         $dropdown = $menu->addChild($this->trans('show'), [ | ||||
| @@ -36,13 +41,10 @@ abstract class AbstractEntityMenuSubscriber implements EventSubscriberInterface | ||||
|                 'dropdown' => 'true', | ||||
|             ], | ||||
|         ]); | ||||
|         foreach (self::FORMAT_TYPES as $format) { | ||||
|         foreach (RESTResponseType::getValues() as $format) { | ||||
|             $dropdown->addChild($format, [ | ||||
|                 'route' => $route, | ||||
|                 'routeParameters' => [ | ||||
|                     'id' => $this->getRequestId($event), | ||||
|                     '_format' => $format, | ||||
|                 ], | ||||
|                 'routeParameters' => $this->getRequestAttributsSubstitutedFormat($event, $format), | ||||
|                 'attributes' => [ | ||||
|                     'icon' => 'fas fa-sign-out-alt', | ||||
|                     'divider_append' => true, | ||||
| @@ -51,22 +53,81 @@ abstract class AbstractEntityMenuSubscriber implements EventSubscriberInterface | ||||
|         } | ||||
|         $dropdown->addChild($this->trans('standard'), [ | ||||
|             'route' => $route, | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'routeParameters' => $this->getRequestAttributs($event), | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fas fa-sign-out-alt', | ||||
|             ], | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $id | ||||
|      * @param array  $parameter | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function trans(string $id, array $parameter = []): string | ||||
|     { | ||||
|         return $this->translator->trans($id, $parameter); | ||||
|     } | ||||
|  | ||||
|     protected function getRequestId(Event $event): int | ||||
|     /** | ||||
|      * @param Event $event | ||||
|      * | ||||
|      * @return int|string | ||||
|      */ | ||||
|     protected function getRequestIdentity(Event $event) | ||||
|     { | ||||
|         return $event->getRequest()->getCurrentRequest()->attributes->get('id'); | ||||
|         return $this->getRequestAttributs($event)->get('identity'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Event $event | ||||
|      * | ||||
|      * @return Request | ||||
|      */ | ||||
|     private function getCurrentRequest(Event $event): Request | ||||
|     { | ||||
|         return $event->getRequest()->getCurrentRequest(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Event $event | ||||
|      * | ||||
|      * @return ParameterBag | ||||
|      */ | ||||
|     private function getRequestAttributs(Event $event): array | ||||
|     { | ||||
|         return $this->getCurrentRequest($event)->attributes->get('_route_params') ?? []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Event  $event | ||||
|      * @param string $format | ||||
|      * | ||||
|      * @return number|string | ||||
|      */ | ||||
|     private function getRequestAttributsSubstitutedFormat(Event $event, string $format): array | ||||
|     { | ||||
|         $attributs = $this->getRequestAttributs($event); | ||||
|         $attributs['_format'] = $format; | ||||
|  | ||||
|         return $attributs; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Event $event | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function shouldShowFormatSelection(Event $event): bool | ||||
|     { | ||||
|         foreach (['identity', 'layer'] as $attribut) { | ||||
|             if (!key_exists($attribut, $this->getRequestAttributs($event))) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,52 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Infinito\Subscriber; | ||||
|  | ||||
| use Infinito\DBAL\Types\MenuEventType; | ||||
| use Infinito\Event\Menu\MenuEvent; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
|  */ | ||||
| class NodeMenuSubscriber extends AbstractEntityMenuSubscriber | ||||
| { | ||||
|     public function onNodeMenuConfigure(MenuEvent $event): void | ||||
|     { | ||||
|         $menu = $event->getItem(); | ||||
|         $this->generateShowDropdown($menu, $event, 'app_source_show'); | ||||
|         $menu->addChild($this->trans('law'), [ | ||||
|             'route' => 'app_node_law', | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fa fa-gavel', | ||||
|             ], | ||||
|         ]); | ||||
|         $menu->addChild($this->trans('parents'), [ | ||||
|             'route' => 'app_node_parents', | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fa fa-female', | ||||
|             ], | ||||
|         ]); | ||||
|         $menu->addChild($this->trans('childs'), [ | ||||
|             'route' => 'app_node_childs', | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fa fa-child', | ||||
|             ], | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public static function getSubscribedEvents() | ||||
|     { | ||||
|         return [ | ||||
|             MenuEventType::NODE => 'onNodeMenuConfigure', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Infinito\Subscriber; | ||||
|  | ||||
| use Infinito\Event\Menu\MenuEvent; | ||||
| use Infinito\DBAL\Types\MenuEventType; | ||||
|  | ||||
| class SourceMenuSubscriber extends AbstractEntityMenuSubscriber | ||||
| { | ||||
|     public function onSourceMenuConfigure(MenuEvent $event): void | ||||
|     { | ||||
|         $menu = $event->getItem(); | ||||
|         $menu->addChild($this->trans('edit'), [ | ||||
|             'route' => 'app_source_edit', | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fas fa-edit', | ||||
|             ], | ||||
|         ]); | ||||
|         $this->generateShowDropdown($menu, $event, 'app_source_show'); | ||||
|         $menu->addChild($this->trans('node'), [ | ||||
|             'route' => 'app_source_node', | ||||
|             'routeParameters' => [ | ||||
|                 'id' => $this->getRequestId($event), | ||||
|             ], | ||||
|             'attributes' => [ | ||||
|                 'icon' => 'fas fa-globe', | ||||
|             ], | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public static function getSubscribedEvents(): array | ||||
|     { | ||||
|         return [ | ||||
|             MenuEventType::SOURCE => 'onSourceMenuConfigure', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -9,22 +9,23 @@ use Knp\Menu\ItemInterface; | ||||
| use Infinito\Event\Menu\MenuEvent; | ||||
| use Infinito\DBAL\Types\MenuEventType; | ||||
| use Infinito\Domain\FixtureManagement\FixtureSource\ImpressumFixtureSource; | ||||
| use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | ||||
|  | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
|  */ | ||||
| class UserMenuSubscriber implements EventSubscriberInterface | ||||
| class UserMenuSubscriber extends AbstractEntityMenuSubscriber implements EventSubscriberInterface | ||||
| { | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     const LAYER_GET_ROUTE = 'infinito_api_rest_layer_read'; | ||||
|  | ||||
|     /** | ||||
|      * @var TokenStorageInterface | ||||
|      */ | ||||
|     private $tokenStorage; | ||||
|  | ||||
|     /** | ||||
|      * @var TranslatorInterface | ||||
|      */ | ||||
|     private $translator; | ||||
|  | ||||
|     /** | ||||
|      * @param TokenStorageInterface $tokenStorage | ||||
|      * @param TranslatorInterface   $translator | ||||
| @@ -32,7 +33,7 @@ class UserMenuSubscriber implements EventSubscriberInterface | ||||
|     public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator) | ||||
|     { | ||||
|         $this->tokenStorage = $tokenStorage; | ||||
|         $this->translator = $translator; | ||||
|         parent::__construct($translator); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -54,22 +55,52 @@ class UserMenuSubscriber implements EventSubscriberInterface | ||||
|                 'icon' => 'fas fa-address-card', | ||||
|             ], | ||||
|         ]); | ||||
|         if ($this->shouldShowFormatSelection($event)) { | ||||
|             $this->generateShowDropdown($menu, $event, self::LAYER_GET_ROUTE); | ||||
|         } | ||||
|         $this->generateUserDropdown($menu); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return TokenInterface|null | ||||
|      */ | ||||
|     private function getToken(): ?TokenInterface | ||||
|     { | ||||
|         return $this->tokenStorage->getToken(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     private function getUsername(): string | ||||
|     { | ||||
|         $token = $this->getToken(); | ||||
|  | ||||
|         return ($token) ? $token->getUsername() : 'user'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     private function getRoles(): ?array | ||||
|     { | ||||
|         $token = $this->getToken(); | ||||
|  | ||||
|         return ($token) ? $token->getRoles() : null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param ItemInterface $menu | ||||
|      */ | ||||
|     private function generateUserDropdown(ItemInterface $menu): void | ||||
|     { | ||||
|         $dropdown = $menu->addChild($this->tokenStorage->getToken() | ||||
|             ->getUsername() ?? 'user', [ | ||||
|         $dropdown = $menu->addChild($this->getUsername(), [ | ||||
|             'attributes' => [ | ||||
|                 'dropdown' => true, | ||||
|                 'icon' => 'fas fa-user', | ||||
|             ], | ||||
|         ]); | ||||
|         if ($this->tokenStorage->getToken()->getRoles()) { | ||||
|         if ($this->getRoles()) { | ||||
|             $dropdown->addChild($this->translator->trans('logout'), [ | ||||
|                 'route' => 'logout', | ||||
|                 'attributes' => [ | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| {# @todo Check out how to use this in the future. If not used, remove! #} | ||||
| {% extends "frames/default.html.twig" %} | ||||
| {% set menu_items = [] %} | ||||
| {% block content %} | ||||
|   | ||||
| @@ -1,11 +0,0 @@ | ||||
| <nav class="navbar navbar-expand-lg navbar-light bg-light"> | ||||
| 	<button class="navbar-toggler" type="button" data-toggle="collapse" | ||||
| 		data-target="#navbarSupportedContent" | ||||
| 		aria-controls="navbarSupportedContent" aria-expanded="false" | ||||
| 		aria-label="Toggle navigation"> | ||||
| 		<span class="navbar-toggler-icon"></span> | ||||
| 	</button> | ||||
| 	<div class="collapse navbar-collapse" id="navbarSupportedContent"> | ||||
| 		{{ knp_menu_render('nodeSubbar', {'currentClass': 'active', 'template': 'frames/structure/navbar/knp_menu.html.twig'}) }} | ||||
| 	</div> | ||||
| </nav> | ||||
| @@ -1,11 +0,0 @@ | ||||
| <nav class="navbar navbar-expand-lg navbar-light bg-light"> | ||||
| 	<button class="navbar-toggler" type="button" data-toggle="collapse" | ||||
| 		data-target="#navbarSupportedContent" | ||||
| 		aria-controls="navbarSupportedContent" aria-expanded="false" | ||||
| 		aria-label="Toggle navigation"> | ||||
| 		<span class="navbar-toggler-icon"></span> | ||||
| 	</button> | ||||
| 	<div class="collapse navbar-collapse" id="navbarSupportedContent"> | ||||
| 		{{ knp_menu_render('sourceNavbar', {'currentClass': 'active', 'template': 'frames/structure/navbar/knp_menu.html.twig'}) }} | ||||
| 	</div> | ||||
| </nav> | ||||
| @@ -2,29 +2,35 @@ | ||||
| 
 | ||||
| namespace Tests\Unit\Entity\Subscriber; | ||||
| 
 | ||||
| use Infinito\Subscriber\SourceMenuSubscriber; | ||||
| use Symfony\Component\Translation\Translator; | ||||
| use Infinito\Event\Menu\MenuEvent; | ||||
| use PHPUnit\Framework\TestCase; | ||||
| use Symfony\Component\HttpFoundation\RequestStack; | ||||
| use Symfony\Component\HttpFoundation\Request; | ||||
| use Knp\Menu\MenuItem; | ||||
| use Knp\Menu\MenuFactory; | ||||
| use Infinito\Subscriber\UserMenuSubscriber; | ||||
| use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; | ||||
| use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; | ||||
| 
 | ||||
| class SourceMenuSubscriberTest extends TestCase | ||||
| /** | ||||
|  * @author kevinfrantz | ||||
|  */ | ||||
| class UserMenuSubscriberTest extends KernelTestCase | ||||
| { | ||||
|     /** | ||||
|      * @var SourceMenuSubscriber | ||||
|      * @var UserMenuSubscriber | ||||
|      */ | ||||
|     public $subscriber; | ||||
| 
 | ||||
|     public function setUp(): void | ||||
|     { | ||||
|         self::bootKernel(); | ||||
|         $translator = new Translator('en'); | ||||
|         $this->subscriber = new SourceMenuSubscriber($translator); | ||||
|         $tokenStorage = self::$container->get(TokenStorageInterface::class); | ||||
|         $this->subscriber = new UserMenuSubscriber($tokenStorage, $translator); | ||||
|     } | ||||
| 
 | ||||
|     public function testOnSourceMenuConfig(): void | ||||
|     public function testOnUserMenuConfigure(): void | ||||
|     { | ||||
|         $factory = new MenuFactory(); | ||||
|         $item = new MenuItem('test', $factory); | ||||
| @@ -33,6 +39,6 @@ class SourceMenuSubscriberTest extends TestCase | ||||
|         $requests = new RequestStack(); | ||||
|         $requests->push($request); | ||||
|         $event = new MenuEvent($factory, $item, $requests); | ||||
|         $this->assertNull($this->subscriber->onSourceMenuConfigure($event)); | ||||
|         $this->assertNull($this->subscriber->onUserMenuConfigure($event)); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user