Added source menu

This commit is contained in:
Kevin Frantz 2018-09-20 14:26:28 +02:00
parent 9ae2290835
commit 3bf84d3ec8
14 changed files with 201 additions and 55 deletions

View File

@ -21,6 +21,11 @@ services:
factory: ['@app.menu_builder', 'userTopbar'] factory: ['@app.menu_builder', 'userTopbar']
tags: tags:
- { name: knp_menu.menu, alias: userTopbar } - { 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 }
# makes classes in src/ available to be used as services # makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name # this creates a service per class whose id is the fully-qualified class name
App\: App\:

View File

@ -1,4 +1,5 @@
<?php <?php
namespace App\Controller; namespace App\Controller;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -7,19 +8,18 @@ use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use App\Creator\Factory\Template\Source\SourceTemplateFactory; use App\Creator\Factory\Template\Source\SourceTemplateFactory;
use FOS\RestBundle\Controller\FOSRestController; use FOS\RestBundle\Controller\FOSRestController;
use App\Form\NameSourceType;
use App\Entity\SourceInterface; use App\Entity\SourceInterface;
use App\Creator\Factory\Template\Source\SourceTemplateFormFactory; use App\Creator\Factory\Template\Source\SourceTemplateFormFactory;
use App\Creator\Factory\Form\Source\SourceFormFactory; use App\Creator\Factory\Form\Source\SourceFormFactory;
/** /**
* @todo IMPLEMENT SECURITY! * @todo IMPLEMENT SECURITY!
*
* @author kevinfrantz * @author kevinfrantz
*/ */
class SourceController extends FOSRestController class SourceController extends FOSRestController
{ {
/** /**
*
* @Route("/source/{id}.{_format}", defaults={"_format"="html"}) * @Route("/source/{id}.{_format}", defaults={"_format"="html"})
*/ */
public function show(Request $request, int $id): Response public function show(Request $request, int $id): Response
@ -28,11 +28,11 @@ class SourceController extends FOSRestController
$view = $this->view($source, 200) $view = $this->view($source, 200)
->setTemplate((new SourceTemplateFactory($source, $request))->getTemplatePath()) ->setTemplate((new SourceTemplateFactory($source, $request))->getTemplatePath())
->setTemplateVar('source'); ->setTemplateVar('source');
return $this->handleView($view); return $this->handleView($view);
} }
/** /**
*
* @Route("/source/{id}/edit.{_format}", defaults={"_format"="html"}) * @Route("/source/{id}/edit.{_format}", defaults={"_format"="html"})
*/ */
public function edit(Request $request, int $id): Response public function edit(Request $request, int $id): Response
@ -44,9 +44,10 @@ class SourceController extends FOSRestController
$source = $form->getData(); $source = $form->getData();
$this->saveSource($source); $this->saveSource($source);
} }
return $this->render((new SourceTemplateFormFactory($source, $request))->getTemplatePath(), array(
return $this->render((new SourceTemplateFormFactory($source, $request))->getTemplatePath(), [
'form' => $form->createView(), 'form' => $form->createView(),
)); ]);
} }
private function loadSource(Request $request, int $id): SourceInterface private function loadSource(Request $request, int $id): SourceInterface
@ -54,9 +55,10 @@ class SourceController extends FOSRestController
$source = $this->getDoctrine() $source = $this->getDoctrine()
->getRepository(AbstractSource::class) ->getRepository(AbstractSource::class)
->find($id); ->find($id);
if (! $source) { if (!$source) {
throw $this->createNotFoundException('No source found for id ' . $id); throw $this->createNotFoundException('No source found for id '.$id);
} }
return $source; return $source;
} }

View File

@ -1,34 +1,35 @@
<?php <?php
namespace App\Creator\Factory\Form\Source; namespace App\Creator\Factory\Form\Source;
use App\Entity\SourceInterface; use App\Entity\SourceInterface;
/** /**
*
* @author kevinfrantz * @author kevinfrantz
*
*/ */
class SourceFormFactory class SourceFormFactory
{ {
const FORM_NAMESPACE = 'App\Form\\'; const FORM_NAMESPACE = 'App\Form\\';
/** /**
* @var SourceInterface * @var SourceInterface
*/ */
private $source; private $source;
public function __construct(SourceInterface $source){ public function __construct(SourceInterface $source)
{
$this->source = $source; $this->source = $source;
} }
public function getNamespace():string{ public function getNamespace(): string
{
return self::FORM_NAMESPACE.$this->getName(); return self::FORM_NAMESPACE.$this->getName();
} }
protected function getName(): string protected function getName(): string
{ {
$reflectionClass = new \ReflectionClass($this->source); $reflectionClass = new \ReflectionClass($this->source);
return $reflectionClass->getShortName().'Type'; return $reflectionClass->getShortName().'Type';
} }
} }

View File

@ -13,7 +13,7 @@ class SourceTemplateFactory
const SOURCE_TEMPLATE_ROOT = 'source'; const SOURCE_TEMPLATE_ROOT = 'source';
const VIEW_FOLDER = 'view'; const VIEW_FOLDER = 'view';
/** /**
* @var SourceInterface * @var SourceInterface
*/ */

View File

@ -1,18 +1,16 @@
<?php <?php
namespace App\Creator\Factory\Template\Source; namespace App\Creator\Factory\Template\Source;
/** /**
*
* @author kevinfrantz * @author kevinfrantz
*
*/ */
class SourceTemplateFormFactory extends SourceTemplateFactory class SourceTemplateFormFactory extends SourceTemplateFactory
{ {
const FORM_FOLDER = 'form'; const FORM_FOLDER = 'form';
public function getTemplatePath(): string public function getTemplatePath(): string
{ {
return parent::SOURCE_TEMPLATE_ROOT.'/'.self::FORM_FOLDER.'/'.$this->generateName().'.'.$this->request->getRequestFormat().'.twig'; return parent::SOURCE_TEMPLATE_ROOT.'/'.self::FORM_FOLDER.'/'.$this->generateName().'.'.$this->request->getRequestFormat().'.twig';
} }
} }

View File

@ -18,6 +18,7 @@ class NameSource extends AbstractSource implements NameSourceInterface
/** /**
* @ORM\Column(type="string",length=255) * @ORM\Column(type="string",length=255)
* @Assert\NotBlank() * @Assert\NotBlank()
*
* @var string * @var string
*/ */
protected $name; protected $name;

View File

@ -0,0 +1,59 @@
<?php
namespace App\Event\Menu\Topbar;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpFoundation\RequestStack;
class SourceMenuEvent extends Event
{
public const EVENT = 'app.menu.source.user';
/**
* @var FactoryInterface
*/
private $factory;
/**
* @var ItemInterface
*/
private $item;
/**
* @var RequestStack
*/
private $request;
public function __construct(FactoryInterface $factory, ItemInterface $item, RequestStack $request)
{
$this->factory = $factory;
$this->item = $item;
$this->request = $request;
}
/**
* @return FactoryInterface
*/
public function getFactory(): FactoryInterface
{
return $this->factory;
}
/**
* @return ItemInterface
*/
public function getItem(): ItemInterface
{
return $this->item;
}
/**
* @return RequestStack
*/
public function getRequest(): RequestStack
{
return $this->request;
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
// src/Menu/Menu.php
namespace App\Menu; namespace App\Menu;
use App\Event\Menu\Topbar\UserMenuEvent; use App\Event\Menu\Topbar\UserMenuEvent;
@ -9,6 +7,7 @@ use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface; use Knp\Menu\ItemInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use App\Event\Menu\Topbar\SourceMenuEvent;
class Menu class Menu
{ {
@ -28,6 +27,19 @@ class Menu
$this->factory = $factory; $this->factory = $factory;
} }
public function SourceNavbar(RequestStack $request): ItemInterface
{
$menu = $this->factory->createItem('root', [
'childrenAttributes' => [
'class' => 'navbar-nav mr-auto',
],
]);
$this->dispatcher->dispatch(SourceMenuEvent::EVENT, new SourceMenuEvent($this->factory, $menu, $request));
return $menu;
}
public function userTopbar(RequestStack $request): ItemInterface public function userTopbar(RequestStack $request): ItemInterface
{ {
$menu = $this->factory->createItem('root', [ $menu = $this->factory->createItem('root', [
@ -36,10 +48,7 @@ class Menu
], ],
]); ]);
$this->dispatcher->dispatch( $this->dispatcher->dispatch(UserMenuEvent::EVENT, new UserMenuEvent($this->factory, $menu, $request));
UserMenuEvent::EVENT,
new UserMenuEvent($this->factory, $menu, $request)
);
return $menu; return $menu;
} }

View File

@ -0,0 +1,53 @@
<?php
namespace App\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Translation\TranslatorInterface;
use App\Event\Menu\Topbar\SourceMenuEvent;
class SourceMenuSubscriber implements EventSubscriberInterface
{
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var TranslatorInterface
*/
private $translator;
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
{
$this->tokenStorage = $tokenStorage;
$this->translator = $translator;
}
public function onSourceMenuConfigure(SourceMenuEvent $event): void
{
$menu = $event->getItem();
$menu->addChild($this->translator->trans('edit'), [
'route' => 'app_source_edit',
'routeParameters' => ['id' => $event->getRequest()->getCurrentRequest()->attributes->get('id')],
'attributes' => [
'icon' => 'fas fa-edit',
],
]);
$menu->addChild($this->translator->trans('show'), [
'route' => 'app_source_show',
'routeParameters' => ['id' => $event->getRequest()->getCurrentRequest()->attributes->get('id')],
'attributes' => [
'icon' => 'fas fa-eye',
],
]);
}
public static function getSubscribedEvents(): array
{
return [
SourceMenuEvent::EVENT => 'onSourceMenuConfigure',
];
}
}

View File

@ -1,4 +1,5 @@
<?php <?php
namespace App\Subscriber; namespace App\Subscriber;
use App\Event\Menu\Topbar\UserMenuEvent; use App\Event\Menu\Topbar\UserMenuEvent;
@ -9,19 +10,16 @@ use Knp\Menu\ItemInterface;
class UserMenuSubscriber implements EventSubscriberInterface class UserMenuSubscriber implements EventSubscriberInterface
{ {
/** /**
*
* @var TokenStorageInterface * @var TokenStorageInterface
*/ */
private $tokenStorage; private $tokenStorage;
/** /**
*
* @var TranslatorInterface * @var TranslatorInterface
*/ */
private $translator; private $translator;
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator) public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
{ {
$this->tokenStorage = $tokenStorage; $this->tokenStorage = $tokenStorage;
@ -31,18 +29,18 @@ class UserMenuSubscriber implements EventSubscriberInterface
public function onUserMenuConfigure(UserMenuEvent $event): void public function onUserMenuConfigure(UserMenuEvent $event): void
{ {
$menu = $event->getItem(); $menu = $event->getItem();
$menu->addChild('start', [ $menu->addChild($this->translator->trans('start'), [
'route' => 'homepage', 'route' => 'homepage',
'attributes' => [ 'attributes' => [
'icon' => 'fab fa-font-awesome-flag' 'icon' => 'fab fa-font-awesome-flag',
] ],
]); ]);
$menu->addChild('imprint', [ $menu->addChild($this->translator->trans('imprint'), [
'route' => 'imprint', 'route' => 'imprint',
'attributes' => [ 'attributes' => [
'icon' => 'fas fa-address-card' 'icon' => 'fas fa-address-card',
] ],
]); ]);
$this->generateUserDropdown($menu); $this->generateUserDropdown($menu);
} }
@ -53,45 +51,45 @@ class UserMenuSubscriber implements EventSubscriberInterface
->getUsername() ?? 'user', [ ->getUsername() ?? 'user', [
'attributes' => [ 'attributes' => [
'dropdown' => true, 'dropdown' => true,
'icon' => 'fas fa-user' 'icon' => 'fas fa-user',
] ],
]); ]);
if ($this->tokenStorage->getToken()->getRoles()) { if ($this->tokenStorage->getToken()->getRoles()) {
$dropdown->addChild('logout', [ $dropdown->addChild($this->translator->trans('logout'), [
'route' => 'logout', 'route' => 'logout',
'attributes' => [ 'attributes' => [
'icon' => 'fas fa-sign-out-alt', 'icon' => 'fas fa-sign-out-alt',
'divider_append' => true 'divider_append' => true,
] ],
]); ]);
$dropdown->addChild('edit profile', [ $dropdown->addChild($this->translator->trans('edit profile'), [
'route' => 'fos_user_profile_edit', 'route' => 'fos_user_profile_edit',
'attributes' => [ 'attributes' => [
'icon' => 'fas fa-user-edit', 'icon' => 'fas fa-user-edit',
'divider_append' => true 'divider_append' => true,
] ],
]); ]);
} else { } else {
$dropdown->addChild('login', [ $dropdown->addChild($this->translator->trans('login'), [
'route' => 'fos_user_security_login', 'route' => 'fos_user_security_login',
'attributes' => [ 'attributes' => [
'divider_append' => true, 'divider_append' => true,
'icon' => 'fas fa-sign-in-alt' 'icon' => 'fas fa-sign-in-alt',
] ],
]); ]);
} }
$dropdown->addChild('register', [ $dropdown->addChild('register', [
'route' => 'fos_user_registration_register', 'route' => 'fos_user_registration_register',
'attributes' => [ 'attributes' => [
'icon' => 'fas fa-file-signature' 'icon' => 'fas fa-file-signature',
] ],
]); ]);
} }
public static function getSubscribedEvents(): array public static function getSubscribedEvents(): array
{ {
return [ return [
UserMenuEvent::EVENT => 'onUserMenuConfigure' UserMenuEvent::EVENT => 'onUserMenuConfigure',
]; ];
} }
} }

View File

@ -0,0 +1,11 @@
<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>

View File

@ -1,6 +1,6 @@
{% extends "frames/default.html.twig" %} {% extends "source/source.html.twig" %}
{% block title %} {% block title %}
{% trans %} {% trans %}
Source Source edit
{% endtrans %} {% endtrans %}
{% endblock %} {% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "frames/default.html.twig" %}
{% block title %}
{% trans %}
Source
{% endtrans %}
{% endblock %}
{% block sub_navigation %}
{% include 'frames/structure/navbar/source_sub.html.twig'%}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "frames/default.html.twig" %} {% extends "source/source.html.twig" %}
{% block title %} {% block title %}
{% trans %} {% trans %}
Source Source