From 4c30b45c0ae01f206a2f33f872ed6e0cb1494c8a Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 19 Mar 2021 15:04:41 +0100 Subject: [PATCH] add node url manager --- config/packages/app.yaml | 1 - config/routes.yaml | 9 ++- config/services.yaml | 4 ++ src/Controller/Site/NodeAdminController.php | 12 +++- src/Controller/Site/PageAdminController.php | 20 ++++-- src/Controller/Site/PageController.php | 26 +++++++ .../Site/NodeEventSubscriber.php | 68 +++++++++++++++++- src/Form/Site/NodeType.php | 1 - src/Repository/Site/NodeRepository.php | 17 +++++ src/Router/SiteRouteLoader.php | 65 +++++++++++++++++ src/Site/SiteRequest.php | 69 +++++++++++++++++++ src/Slugify/Slugify.php | 31 +++++++++ templates/admin/layout.html.twig | 8 +++ templates/site/page/simple/page.html.twig | 6 ++ templates/site/page_admin/index.html.twig | 59 ++++++++++++++++ .../site/tree_admin/navigation.html.twig | 6 ++ 16 files changed, 387 insertions(+), 15 deletions(-) create mode 100644 src/Controller/Site/PageController.php create mode 100644 src/Router/SiteRouteLoader.php create mode 100644 src/Site/SiteRequest.php create mode 100644 src/Slugify/Slugify.php create mode 100644 templates/site/page/simple/page.html.twig create mode 100644 templates/site/page_admin/index.html.twig diff --git a/config/packages/app.yaml b/config/packages/app.yaml index 52aad8e..5091281 100644 --- a/config/packages/app.yaml +++ b/config/packages/app.yaml @@ -5,4 +5,3 @@ app: name: 'Page simple' templates: - {name: "Template 1", file: "site/page/simple/page.html.twig"} - - {name: "Template 2", file: "site/page/simple/page2.html.twig"} diff --git a/config/routes.yaml b/config/routes.yaml index 3a94441..05e7257 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -2,11 +2,10 @@ # path: / # controller: App\Controller\DefaultController::index -#https://symfony.com/doc/current/routing/custom_route_loader.html -#admin_routes: -# resource: 'admin_route_loader::loadRoutes' -# type: service -# +site_route: + resource: 'site.route_loader::loadRoutes' + type: extra + 2fa_login: path: /2fa defaults: diff --git a/config/services.yaml b/config/services.yaml index c8fba38..343eac5 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -27,6 +27,10 @@ services: resource: '../src/Controller/' tags: ['controller.service_arguments'] + site.route_loader: + class: App\Router\SiteRouteLoader + tags: [routing.loader] + gedmo.listener.tree: class: Gedmo\Tree\TreeListener tags: diff --git a/src/Controller/Site/NodeAdminController.php b/src/Controller/Site/NodeAdminController.php index 983814a..fd1a315 100644 --- a/src/Controller/Site/NodeAdminController.php +++ b/src/Controller/Site/NodeAdminController.php @@ -66,7 +66,8 @@ class NodeAdminController extends AdminController $form->get('pageEntity')->getData(), $form->get('pageType')->getData(), $entity, - $pageFactory + $pageFactory, + $pageLocator ); $entityManager->update($entity); @@ -111,7 +112,8 @@ class NodeAdminController extends AdminController $form->get('pageEntity')->getData(), $form->get('pageType')->getData(), $entity, - $pageFactory + $pageFactory, + $pageLocator ); $entityManager->update($entity); @@ -137,11 +139,15 @@ class NodeAdminController extends AdminController ?Page $pageEntity, string $pageType, Entity $entity, - PageFactory $pageFactory + PageFactory $pageFactory, + PageLocator $pageLocator ) { if ($pageAction === 'new') { + $pageConfiguration = $pageLocator->getPage($pageType); $page = $pageFactory->create($pageType, $entity->getLabel()); + $page->setTemplate($pageConfiguration->getTemplates()[0]['file']); + $entity->setPage($page); } elseif ($pageAction === 'existing') { if ($pageEntity) { diff --git a/src/Controller/Site/PageAdminController.php b/src/Controller/Site/PageAdminController.php index 182373c..d86d875 100644 --- a/src/Controller/Site/PageAdminController.php +++ b/src/Controller/Site/PageAdminController.php @@ -9,7 +9,7 @@ use App\Form\Site\Page\PageType as EntityType; use App\Manager\EntityManager; use App\Page\FooPage; use App\Page\SimplePage; -use App\Repository\Site\Page\PageRepositoryQuery as EntityRepositoryQuery; +use App\Repository\Site\Page\PageRepositoryQuery as RepositoryQuery; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; @@ -19,6 +19,18 @@ use Symfony\Component\Routing\Annotation\Route; */ class PageAdminController extends AdminController { + /** + * @Route("/{page}", name="admin_site_page_index", requirements={"page": "\d+"}) + */ + public function index(int $page = 1, RepositoryQuery $query, Request $request): Response + { + $pager = $query->paginate($page); + + return $this->render('site/page_admin/index.html.twig', [ + 'pager' => $pager, + ]); + } + /** * @Route("/new", name="admin_site_page_new") */ @@ -44,7 +56,7 @@ class PageAdminController extends AdminController int $entity, EntityFactory $factory, EntityManager $entityManager, - EntityRepositoryQuery $repositoryQuery, + RepositoryQuery $repositoryQuery, Request $request ): Response { $entity = $repositoryQuery->filterById($entity)->findOne(); @@ -83,11 +95,11 @@ class PageAdminController extends AdminController $this->addFlash('success', 'Données supprimée..'); } - return $this->redirectToRoute('admin_site_tree_index'); + return $this->redirectToRoute('admin_site_page_index'); } public function getSection(): string { - return ''; + return 'site_page'; } } diff --git a/src/Controller/Site/PageController.php b/src/Controller/Site/PageController.php new file mode 100644 index 0000000..89ee57a --- /dev/null +++ b/src/Controller/Site/PageController.php @@ -0,0 +1,26 @@ +getPage()) { + throw $this->createNotFoundException(); + } + + return $this->render($siteRequest->getPage()->getTemplate(), [ + '_node' => $siteRequest->getNode(), + '_page' => $siteRequest->getPage(), + '_menu' => $siteRequest->getMenu(), + '_navigation' => $siteRequest->getNavigation(), + ]); + } +} diff --git a/src/EventSuscriber/Site/NodeEventSubscriber.php b/src/EventSuscriber/Site/NodeEventSubscriber.php index 0d313b6..16fabda 100644 --- a/src/EventSuscriber/Site/NodeEventSubscriber.php +++ b/src/EventSuscriber/Site/NodeEventSubscriber.php @@ -9,6 +9,11 @@ use App\EventSuscriber\EntityManagerEventSubscriber; use App\Factory\Site\NodeFactory; use App\Manager\EntityManager; use App\Repository\Site\NodeRepository; +use App\Slugify\Slugify; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\BufferedOutput; /** * class NodeEventSubscriber. @@ -19,15 +24,21 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber { protected NodeFactory $nodeFactory; protected EntityManager $entityManager; + protected KernelInterface $kernel; + protected Slugify $slugify; public function __construct( NodeFactory $nodeFactory, NodeRepository $nodeRepository, - EntityManager $entityManager + EntityManager $entityManager, + KernelInterface $kernel, + Slugify $slugify ) { $this->nodeFactory = $nodeFactory; $this->nodeRepository = $nodeRepository; $this->entityManager = $entityManager; + $this->kernel = $kernel; + $this->slugify = $slugify; } public function support(EntityInterface $entity) @@ -35,6 +46,61 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber return $entity instanceof Node; } + public function onPreUpdate(EntityManagerEvent $event) + { + if (!$this->support($event->getEntity())) { + return; + } + + $node = $event->getEntity(); + + if ($node->getUrl()) { + $generatedUrl = $node->getUrl(); + } else { + $path = []; + $parent = $node->getParent(); + + if ($parent && $parent->getUrl()) { + $pPath = trim($parent->getUrl(), '/'); + + if ($pPath) { + $path[] = $pPath; + } + } + + $path[] = $this->slugify->slugify($node->getLabel()); + + $generatedUrl = '/'.implode('/', $path); + } + + $urlExists = $this->nodeRepository->urlExists($generatedUrl, $node); + + if ($urlExists) { + $number = 1; + + while ($this->nodeRepository->urlExists($generatedUrl.'-'.$number, $node)) { + $number++; + } + + $generatedUrl = $generatedUrl.'-'.$number; + } + + $node->setUrl($generatedUrl); + } + + public function onUpdate(EntityManagerEvent $event) + { + $application = new Application($this->kernel); + $application->setAutoExit(false); + + $input = new ArrayInput([ + 'command' => 'cache:clear', + ]); + + $output = new BufferedOutput(); + $application->run($input, $output); + } + public function onDelete(EntityManagerEvent $event) { if (!$this->support($event->getEntity())) { diff --git a/src/Form/Site/NodeType.php b/src/Form/Site/NodeType.php index b4c70dd..c78e856 100644 --- a/src/Form/Site/NodeType.php +++ b/src/Form/Site/NodeType.php @@ -107,7 +107,6 @@ class NodeType extends AbstractType ; }, 'constraints' => [ - new NotBlank(), ], ] ); diff --git a/src/Repository/Site/NodeRepository.php b/src/Repository/Site/NodeRepository.php index a6e9901..519b410 100644 --- a/src/Repository/Site/NodeRepository.php +++ b/src/Repository/Site/NodeRepository.php @@ -12,4 +12,21 @@ class NodeRepository extends NestedTreeRepository { parent::__construct($manager, $manager->getClassMetadata(Node::class)); } + + public function urlExists($url, Node $node) + { + $query = $this->createQueryBuilder('n') + ->where('n.url = :url') + ->setParameter(':url', $url); + + if ($node->getId()) { + $query + ->andWhere('n.id != :id') + ->setParameter(':id', $node->getId()); + } + + return $query->getQuery() + ->setMaxResults(1) + ->getOneOrNullResult(); + } } diff --git a/src/Router/SiteRouteLoader.php b/src/Router/SiteRouteLoader.php new file mode 100644 index 0000000..1aba2f0 --- /dev/null +++ b/src/Router/SiteRouteLoader.php @@ -0,0 +1,65 @@ + + */ +class SiteRouteLoader extends Loader +{ + protected NavigationRepositoryQuery $navigationQuery; + protected $isLoaded = false; + + public function __construct(NavigationRepositoryQuery $navigationQuery) + { + $this->navigationQuery = $navigationQuery; + } + + public function load($resource, ?string $type = null) + { + if (true === $this->isLoaded) { + throw new \RuntimeException('Do not add the "extra" loader twice'); + } + + $routes = new RouteCollection(); + $navigations = $this->navigationQuery->find(); + + foreach ($navigations as $navigation) { + foreach ($navigation->getMenus() as $menu) { + foreach ($menu->getRootNode()->getAllChildren() as $node) { + $requirements = []; + + $defaults = [ + '_controller' => PageController::class.'::show', + '_node' => $node->getId(), + '_menu' => $menu->getId(), + '_page' => $node->getPage() ? $node->getPage()->getId() : null, + '_navigation' => $navigation->getId(), + ]; + + $route = new Route($node->getUrl(), $defaults, $requirements); + $route->setHost($navigation->getDomain()); + + $routes->add('site_page_'.$node->getId(), $route); + } + } + } + + $this->isLoaded = true; + + return $routes; + } + + public function supports($resource, string $type = null) + { + return 'extra' === $type; + } +} diff --git a/src/Site/SiteRequest.php b/src/Site/SiteRequest.php new file mode 100644 index 0000000..8217ced --- /dev/null +++ b/src/Site/SiteRequest.php @@ -0,0 +1,69 @@ + + */ +class SiteRequest +{ + protected RequestStack $requestStack; + protected NodeRepository $nodeRepository; + protected NavigationRepositoryQuery $navigationRepositoryQuery; + protected PageRepositoryQuery $pageRepositoryQuery; + + public function __construct(RequestStack $requestStack, NodeRepository $nodeRepository) + { + $this->requestStack = $requestStack; + $this->nodeRepository = $nodeRepository; + } + + public function getNode(): ?Node + { + $request = $this->requestStack->getCurrentRequest(); + + if ($request->attributes->has('_node')) { + return $this->nodeRepository->findOneBy([ + 'id' => $request->attributes->get('_node'), + ]); + } + + return null; + } + + public function getPage(): ?Page + { + $node = $this->getNode(); + + if ($node && $node->getPage()) { + return $node->getPage(); + } + + return null; + } + + public function getMenu(): ?Menu + { + $node = $this->getNode(); + + return null !== $node ? $node->getMenu() : null; + } + + public function getNavigation(): ?Navigation + { + $menu = $this->getMenu(); + + return null !== $menu ? $menu->getNavigation() : null; + } +} diff --git a/src/Slugify/Slugify.php b/src/Slugify/Slugify.php new file mode 100644 index 0000000..76976b3 --- /dev/null +++ b/src/Slugify/Slugify.php @@ -0,0 +1,31 @@ + + */ +class Slugify +{ + public function slugify($data) + { + return $this->create()->slugify($data); + } + + protected function create(): BaseSlugify + { + $slugify = new BaseSlugify([ + 'separator' => '-', + 'lowercase' => false, + ]); + + $slugify->activateRuleSet('french'); + $slugify->addRule("'", ''); + + return $slugify; + } +} diff --git a/templates/admin/layout.html.twig b/templates/admin/layout.html.twig index f169f87..73a5e1f 100644 --- a/templates/admin/layout.html.twig +++ b/templates/admin/layout.html.twig @@ -71,6 +71,14 @@ Arborescence + + {% endif %} diff --git a/templates/site/page/simple/page.html.twig b/templates/site/page/simple/page.html.twig new file mode 100644 index 0000000..3b78c55 --- /dev/null +++ b/templates/site/page/simple/page.html.twig @@ -0,0 +1,6 @@ +Node : {{ _node.label }}
+Menu : {{ _menu.label }}
+Navigation : {{ _navigation.label }}
+ +Page : {{ _page.title.value }}
+Content : {{ _page.content.value|raw }}
diff --git a/templates/site/page_admin/index.html.twig b/templates/site/page_admin/index.html.twig new file mode 100644 index 0000000..65fce23 --- /dev/null +++ b/templates/site/page_admin/index.html.twig @@ -0,0 +1,59 @@ +{% extends 'admin/layout.html.twig' %} + +{% block body %} +
+
+
+

Pages

+
+
+ + {{ knp_pagination_render(pager) }} +
+ + + + + + + + + + {% for item in pager %} + {% set edit = path('admin_site_page_edit', {entity: item.id}) %} + + + + + + {% else %} + + + + {% endfor %} + +
NomActions
+ + {{ item.name }} + + + + + + + +
+ + +
+
+
+ +
+
+ Aucun résultat +
+
+{% endblock %} diff --git a/templates/site/tree_admin/navigation.html.twig b/templates/site/tree_admin/navigation.html.twig index 70b40aa..68a9ede 100644 --- a/templates/site/tree_admin/navigation.html.twig +++ b/templates/site/tree_admin/navigation.html.twig @@ -111,6 +111,12 @@
{{ node.label }} + + {% if node.url %} + + {{ node.url }} + + {% endif %}