From 237b105289cf70ef69b915cf4039031a732c9655 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Fri, 19 Mar 2021 12:10:52 +0100 Subject: [PATCH] add node ang page edition --- config/bundles.php | 1 + config/packages/app.yaml | 8 ++ config/packages/doctrine.yaml | 6 +- src/Bundle/AppBundle.php | 24 ++++ src/Controller/Site/NodeAdminController.php | 64 ++++++++++- src/Controller/Site/PageAdminController.php | 19 ++- src/DependencyInjection/AppExtension.php | 29 +++++ src/DependencyInjection/Configuration.php | 44 +++++++ src/Entity/Site/Node.php | 19 +++ src/Entity/Site/Page/Block.php | 1 + src/Entity/Site/Page/Page.php | 37 ++++++ src/Factory/Site/Page/PageFactory.php | 7 +- src/Form/Site/NodeType.php | 72 +++++++++++- src/Form/Site/Page/PageType.php | 15 +++ src/{ => Site}/Page/SimplePage.php | 2 +- src/Site/PageConfiguration.php | 51 +++++++++ src/Site/PageLocator.php | 48 ++++++++ templates/site/node_admin/_form.html.twig | 108 ++++++++++++++++++ templates/site/node_admin/edit.html.twig | 2 +- templates/site/node_admin/new.html.twig | 2 +- templates/site/page_admin/_form.html.twig | 13 ++- templates/site/page_admin/edit.html.twig | 16 +++ .../site/tree_admin/navigation.html.twig | 20 +++- 23 files changed, 583 insertions(+), 25 deletions(-) create mode 100644 config/packages/app.yaml create mode 100644 src/Bundle/AppBundle.php create mode 100644 src/DependencyInjection/AppExtension.php create mode 100644 src/DependencyInjection/Configuration.php rename src/{ => Site}/Page/SimplePage.php (98%) create mode 100644 src/Site/PageConfiguration.php create mode 100644 src/Site/PageLocator.php create mode 100644 templates/site/node_admin/_form.html.twig diff --git a/config/bundles.php b/config/bundles.php index b1227e8..2afb83c 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -17,4 +17,5 @@ return [ Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true], Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true], Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], + App\Bundle\AppBundle::class => ['all' => true], ]; diff --git a/config/packages/app.yaml b/config/packages/app.yaml new file mode 100644 index 0000000..52aad8e --- /dev/null +++ b/config/packages/app.yaml @@ -0,0 +1,8 @@ +app: + site: + pages: + App\Site\Page\SimplePage: + 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/packages/doctrine.yaml b/config/packages/doctrine.yaml index 9781681..0019ee1 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -16,11 +16,11 @@ doctrine: dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity' alias: App\Entity - App\Page: + App\Site\Page: is_bundle: false type: annotation - dir: '%kernel.project_dir%/src/Page' - prefix: 'App\Page' + dir: '%kernel.project_dir%/src/Site/Page' + prefix: 'App\Site\Page' gedmo_tree: type: annotation prefix: Gedmo\Tree\Entity diff --git a/src/Bundle/AppBundle.php b/src/Bundle/AppBundle.php new file mode 100644 index 0000000..4ca9ef9 --- /dev/null +++ b/src/Bundle/AppBundle.php @@ -0,0 +1,24 @@ +create($node->getMenu()); - $form = $this->createForm(EntityType::class, $entity); + $form = $this->createForm(EntityType::class, $entity, [ + 'pages' => $pageLocator->getPages(), + ]); if ($request->isMethod('POST')) { $form->handleRequest($request); @@ -46,17 +53,24 @@ class NodeAdminController extends AdminController if ('above' === $position) { $nodeRepository->persistAsLastChild($entity, $node); - $entityManager->flush(); } else { if ('after' === $position) { $nodeRepository->persistAsNextSiblingOf($entity, $node); } elseif ('before' === $position) { $nodeRepository->persistAsPrevSiblingOf($entity, $node); } - - $entityManager->flush(); } + $this->handlePageAssociation( + $form->get('pageAction')->getData(), + $form->get('pageEntity')->getData(), + $form->get('pageType')->getData(), + $entity, + $pageFactory + ); + + $entityManager->update($entity); + $this->addFlash('success', 'Donnée enregistrée.'); } else { $this->addFlash('warning', 'Le formulaire est invalide.'); @@ -77,13 +91,29 @@ class NodeAdminController extends AdminController /** * @Route("/edit/{entity}", name="admin_site_node_edit") */ - public function edit(Entity $entity, EntityManager $entityManager, Request $request): Response { - $form = $this->createForm(EntityType::class, $entity); + public function edit( + Entity $entity, + EntityManager $entityManager, + PageFactory $pageFactory, + PageLocator $pageLocator, + Request $request + ): Response { + $form = $this->createForm(EntityType::class, $entity, [ + 'pages' => $pageLocator->getPages(), + ]); if ($request->isMethod('POST')) { $form->handleRequest($request); if ($form->isValid()) { + $this->handlePageAssociation( + $form->get('pageAction')->getData(), + $form->get('pageEntity')->getData(), + $form->get('pageType')->getData(), + $entity, + $pageFactory + ); + $entityManager->update($entity); $this->addFlash('success', 'Donnée enregistrée.'); @@ -102,6 +132,28 @@ class NodeAdminController extends AdminController ]); } + protected function handlePageAssociation( + string $pageAction, + ?Page $pageEntity, + string $pageType, + Entity $entity, + PageFactory $pageFactory + ) + { + if ($pageAction === 'new') { + $page = $pageFactory->create($pageType, $entity->getLabel()); + $entity->setPage($page); + } elseif ($pageAction === 'existing') { + if ($pageEntity) { + $entity->setPage($pageEntity); + } else { + $this->addFlash('info', 'Aucun changement de page effectué.'); + } + } elseif ($pageAction === 'none') { + $entity->setPage(null); + } + } + /** * @Route("/move/{entity}", name="admin_site_node_move") */ diff --git a/src/Controller/Site/PageAdminController.php b/src/Controller/Site/PageAdminController.php index d69ba1a..182373c 100644 --- a/src/Controller/Site/PageAdminController.php +++ b/src/Controller/Site/PageAdminController.php @@ -47,11 +47,6 @@ class PageAdminController extends AdminController EntityRepositoryQuery $repositoryQuery, Request $request ): Response { - // $page = $factory->create(PageFoo::class); - // $page->setName('Page de test 2'); - // $entityManager->update($page); - // die; - $entity = $repositoryQuery->filterById($entity)->findOne(); $form = $this->createForm(EntityType::class, $entity); @@ -77,6 +72,20 @@ class PageAdminController extends AdminController ]); } + /** + * @Route("/delete/{entity}", name="admin_site_page_delete", methods={"DELETE"}) + */ + public function delete(Entity $entity, EntityManager $entityManager, Request $request): Response + { + if ($this->isCsrfTokenValid('delete'.$entity->getId(), $request->request->get('_token'))) { + $entityManager->delete($entity); + + $this->addFlash('success', 'Données supprimée..'); + } + + return $this->redirectToRoute('admin_site_tree_index'); + } + public function getSection(): string { return ''; diff --git a/src/DependencyInjection/AppExtension.php b/src/DependencyInjection/AppExtension.php new file mode 100644 index 0000000..97be534 --- /dev/null +++ b/src/DependencyInjection/AppExtension.php @@ -0,0 +1,29 @@ +getConfiguration($configs, $container); + $config = $this->processConfiguration($configuration, $configs); + + $container->setParameter('app', $config); + } + + /** + * {@inheritDoc} + */ + public function getConfiguration(array $configs, ContainerBuilder $container) + { + return new Configuration(); + } +} diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php new file mode 100644 index 0000000..b710766 --- /dev/null +++ b/src/DependencyInjection/Configuration.php @@ -0,0 +1,44 @@ +getRootNode() + ->children() + ->arrayNode('site') + ->children() + ->arrayNode('pages') + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->arrayNode('templates') + ->prototype('array') + ->children() + ->scalarNode('name') + ->cannotBeEmpty() + ->end() + ->scalarNode('file') + ->cannotBeEmpty() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/Entity/Site/Node.php b/src/Entity/Site/Node.php index 9dd7e05..b0b08f4 100644 --- a/src/Entity/Site/Node.php +++ b/src/Entity/Site/Node.php @@ -4,6 +4,7 @@ namespace App\Entity\Site; use App\Doctrine\Timestampable; use App\Entity\EntityInterface; +use App\Entity\Site\Page\Page; use App\Repository\Site\NodeRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -85,6 +86,12 @@ class Node implements EntityInterface */ private $children; + /** + * @ORM\ManyToOne(targetEntity=Page::class, inversedBy="nodes", cascade={"persist"}) + * @ORM\JoinColumn(nullable=true, onDelete="SET NULL") + */ + private $page; + public function __construct() { $this->children = new ArrayCollection(); @@ -260,4 +267,16 @@ class Node implements EntityInterface return trim($prefix.' '.$this->getLabel()); } + + public function getPage(): ?Page + { + return $this->page; + } + + public function setPage(?Page $page): self + { + $this->page = $page; + + return $this; + } } diff --git a/src/Entity/Site/Page/Block.php b/src/Entity/Site/Page/Block.php index 22e23a5..0909d0d 100644 --- a/src/Entity/Site/Page/Block.php +++ b/src/Entity/Site/Page/Block.php @@ -33,6 +33,7 @@ class Block /** * @ORM\ManyToOne(targetEntity=Page::class, inversedBy="blocks") + * @ORM\JoinColumn(onDelete="CASCADE") */ private $page; diff --git a/src/Entity/Site/Page/Page.php b/src/Entity/Site/Page/Page.php index 97aba44..6111f2f 100644 --- a/src/Entity/Site/Page/Page.php +++ b/src/Entity/Site/Page/Page.php @@ -4,6 +4,7 @@ namespace App\Entity\Site\Page; use App\Doctrine\Timestampable; use App\Entity\EntityInterface; +use App\Entity\Site\Node; use App\Repository\Site\Page\PageRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -62,9 +63,15 @@ class Page implements EntityInterface */ private $ogDescription; + /** + * @ORM\OneToMany(targetEntity=Node::class, mappedBy="page") + */ + private $nodes; + public function __construct() { $this->blocks = new ArrayCollection(); + $this->nodes = new ArrayCollection(); } public function getId(): ?int @@ -208,4 +215,34 @@ class Page implements EntityInterface return $this; } + + /** + * @return Collection|Node[] + */ + public function getNodes(): Collection + { + return $this->nodes; + } + + public function addNode(Node $node): self + { + if (!$this->nodes->contains($node)) { + $this->nodes[] = $node; + $node->setPage($this); + } + + return $this; + } + + public function removeNode(Node $node): self + { + if ($this->nodes->removeElement($node)) { + // set the owning side to null (unless already changed) + if ($node->getPage() === $this) { + $node->setPage(null); + } + } + + return $this; + } } diff --git a/src/Factory/Site/Page/PageFactory.php b/src/Factory/Site/Page/PageFactory.php index 98a8ba0..64e3725 100644 --- a/src/Factory/Site/Page/PageFactory.php +++ b/src/Factory/Site/Page/PageFactory.php @@ -11,8 +11,11 @@ use App\Entity\Site\Page\Page; */ class PageFactory { - public function create(string $className): Page + public function create(string $className, string $name): Page { - return new $className(); + $entity = new $className(); + $entity->setName($name); + + return $entity; } } diff --git a/src/Form/Site/NodeType.php b/src/Form/Site/NodeType.php index 0382085..b4c70dd 100644 --- a/src/Form/Site/NodeType.php +++ b/src/Form/Site/NodeType.php @@ -9,6 +9,9 @@ use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\NotBlank; +use App\Entity\Site\Page\Page; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Doctrine\ORM\EntityRepository; class NodeType extends AbstractType { @@ -42,6 +45,73 @@ class NodeType extends AbstractType ] ); + $actions = [ + 'Nouvelle page' => 'new', + 'Associer à une page existante' => 'existing', + 'Aucune page' => 'none', + ]; + + if ($builder->getData()->getId()) { + $actions['Garder la configuration actuelle'] = 'keep'; + } + + $builder->add( + 'pageAction', + ChoiceType::class, + [ + 'label' => false, + 'required' => true, + 'expanded' => true, + 'mapped' => false, + 'choices' => $actions, + 'constraints' => [ + new NotBlank(), + ], + ] + ); + + $builder->add( + 'pageType', + ChoiceType::class, + [ + 'label' => false, + 'required' => true, + 'mapped' => false, + 'choices' => call_user_func(function() use ($options) { + $choices = []; + + foreach ($options['pages'] as $page) { + $choices[$page->getName()] = $page->getClassName(); + } + + return $choices; + }), + 'constraints' => [ + new NotBlank(), + ], + ] + ); + + $builder->add( + 'pageEntity', + EntityType::class, + [ + 'label' => false, + 'required' => true, + 'mapped' => false, + 'class' => Page::class, + 'choice_label' => 'name', + 'query_builder' => function (EntityRepository $repo) { + return $repo->createQueryBuilder('p') + ->orderBy('p.name', 'ASC') + ; + }, + 'constraints' => [ + new NotBlank(), + ], + ] + ); + if ($builder->getData()->getId() === null) { $builder->add( 'position', @@ -69,7 +139,7 @@ class NodeType extends AbstractType { $resolver->setDefaults([ 'data_class' => Node::class, - 'pages' => null, + 'pages' => [], ]); } } diff --git a/src/Form/Site/Page/PageType.php b/src/Form/Site/Page/PageType.php index 668958d..e80c8d8 100644 --- a/src/Form/Site/Page/PageType.php +++ b/src/Form/Site/Page/PageType.php @@ -7,11 +7,26 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\NotBlank; class PageType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { + $builder->add( + 'name', + TextType::class, + [ + 'label' => 'Nom', + 'required' => true, + 'attr' => [ + ], + 'constraints' => [ + new NotBlank(), + ], + ] + ); + $builder->add( 'metaTitle', TextType::class, diff --git a/src/Page/SimplePage.php b/src/Site/Page/SimplePage.php similarity index 98% rename from src/Page/SimplePage.php rename to src/Site/Page/SimplePage.php index c48744f..7652d98 100644 --- a/src/Page/SimplePage.php +++ b/src/Site/Page/SimplePage.php @@ -1,6 +1,6 @@ + */ +class PageConfiguration +{ + protected string $className; + protected string $name; + protected array $templates; + + public function setClassName(string $className): self + { + $this->className = $className; + + return $this; + } + + public function getClassName(): string + { + return $this->className; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function setTemplates(array $templates): self + { + $this->templates = $templates; + + return $this; + } + + public function getTemplates(): array + { + return $this->templates; + } +} diff --git a/src/Site/PageLocator.php b/src/Site/PageLocator.php new file mode 100644 index 0000000..734d59d --- /dev/null +++ b/src/Site/PageLocator.php @@ -0,0 +1,48 @@ + + */ +class PageLocator +{ + protected array $params; + protected array $pages; + + public function __construct(ParameterBagInterface $bag) + { + $this->params = $bag->get('app'); + $this->loadPages(); + } + + protected function loadPages(): void + { + $params = $this->params['site']['pages'] ?? []; + + foreach ($params as $className => $conf) { + $pageConfiguration = new PageConfiguration(); + $pageConfiguration + ->setClassName($className) + ->setName($conf['name']) + ->setTemplates($conf['templates']) + ; + + $this->pages[$className] = $pageConfiguration; + } + } + + public function getPages(): array + { + return $this->pages; + } + + public function getPage($className) + { + return $this->pages[$className] ?? null; + } +} diff --git a/templates/site/node_admin/_form.html.twig b/templates/site/node_admin/_form.html.twig new file mode 100644 index 0000000..49be5c6 --- /dev/null +++ b/templates/site/node_admin/_form.html.twig @@ -0,0 +1,108 @@ +{{ form_row(form.label) }} +{{ form_row(form.url) }} + +{% if form.position is defined %} + {{ form_row(form.position) }} +{% endif %} + +
+
+ {% set action = form.pageAction[0] %} + {% set options = not entity.id ? {'attr': {'checked': 'checked'}} : {} %} + +
+

+ + +
+ {{ form_row(action, options) }} +
+

+
+
+
+ {{ form_row(form.pageType) }} +
+
+
+
+ {% set action = form.pageAction[1] %} + +
+

+ + +
+ {{ form_row(action) }} +
+

+
+
+
+ {{ form_row(form.pageEntity) }} +
+
+
+
+ {% set action = form.pageAction[2] %} + +
+

+ + +
+ {{ form_row(action) }} +
+

+
+
+
+ Aucune action +
+
+
+ + {% if entity.id %} +
+ {% set action = form.pageAction[3] %} + {% set options = {'attr': {'checked': 'checked'}} %} + +
+

+ + +
+ {{ form_row(action, options) }} +
+

+
+
+
+ Aucune action +
+
+
+ {% endif %} +
+ +{{ form_rest(form) }} diff --git a/templates/site/node_admin/edit.html.twig b/templates/site/node_admin/edit.html.twig index b7b8f03..598e586 100644 --- a/templates/site/node_admin/edit.html.twig +++ b/templates/site/node_admin/edit.html.twig @@ -8,7 +8,7 @@ - diff --git a/templates/site/page_admin/edit.html.twig b/templates/site/page_admin/edit.html.twig index 11aa800..2e4b6e5 100644 --- a/templates/site/page_admin/edit.html.twig +++ b/templates/site/page_admin/edit.html.twig @@ -13,6 +13,17 @@ Enregistrer + + + @@ -29,4 +40,9 @@ {{ form_rest(form) }} + +
+ + +
{% endblock %} diff --git a/templates/site/tree_admin/navigation.html.twig b/templates/site/tree_admin/navigation.html.twig index b457f55..70b40aa 100644 --- a/templates/site/tree_admin/navigation.html.twig +++ b/templates/site/tree_admin/navigation.html.twig @@ -70,30 +70,42 @@ {% set move = path('admin_site_node_move', {entity: node.id}) %} {% set edit = path('admin_site_node_edit', {entity: node.id}) %} {% set new = path('admin_site_node_new', {node: node.id}) %} +
+ {% if node.page %} + + + Page + + {% endif %} + - - + +