From 633e16771ad36a34a1b81add75e649829454a8d3 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Mon, 22 Mar 2021 12:42:48 +0100 Subject: [PATCH] add node attributes and node paramters --- assets/css/admin.scss | 1 - assets/js/addons/form-collection.js | 4 +- core/Entity/Site/Node.php | 59 ++++ core/Entity/Site/Page/Block.php | 2 +- .../Site/NodeEventSubscriber.php | 19 +- .../Site/Page/BlockEventSubscriber.php | 58 +++ core/Form/Site/NodeAttributeType.php | 50 +++ core/Form/Site/NodeParameterType.php | 62 ++++ core/Form/Site/NodeType.php | 39 ++ core/Router/SiteRouteLoader.php | 9 +- core/Slugify/CodeSlugify.php | 9 +- core/Slugify/Slugify.php | 2 +- src/Controller/Blog/PostAdminController.php | 6 +- src/Entity/Page/SimplePage.php | 29 +- templates/blog/post_admin/index.html.twig | 2 +- templates/blog/post_admin/show.html.twig | 2 +- templates/site/node_admin/_form.html.twig | 334 +++++++++++++----- templates/site/node_admin/edit.html.twig | 4 - .../site/tree_admin/navigation.html.twig | 6 +- 19 files changed, 579 insertions(+), 118 deletions(-) create mode 100644 core/EventSuscriber/Site/Page/BlockEventSubscriber.php create mode 100644 core/Form/Site/NodeAttributeType.php create mode 100644 core/Form/Site/NodeParameterType.php diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 42b932e..a6ee269 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -342,7 +342,6 @@ table.table-fixed, .table-fixed > table { *[data-collection-delete-container] { cursor: pointer; - margin-top: 35px; } *[data-collection-add] { diff --git a/assets/js/addons/form-collection.js b/assets/js/addons/form-collection.js index 8345a0f..9e5145c 100644 --- a/assets/js/addons/form-collection.js +++ b/assets/js/addons/form-collection.js @@ -44,13 +44,13 @@ const FormCollection = () => { CollectionInitilizedAndUpdated ); - $('*[data-collection]').on( + $('body').on( 'click', '*[data-collection-delete], *[data-collection-delete-container]', DeleteHandler ); - $('*[data-collection-add]').click((e) => { + $('body').on('click', '*[data-collection-add]', (e) => { e.stopPropagation() const collectionId = $(e.target).attr('data-collection-add') diff --git a/core/Entity/Site/Node.php b/core/Entity/Site/Node.php index 9b89de4..d0697e5 100644 --- a/core/Entity/Site/Node.php +++ b/core/Entity/Site/Node.php @@ -97,6 +97,21 @@ class Node implements EntityInterface */ private $code; + /** + * @ORM\Column(type="array", nullable=true) + */ + private $parameters = []; + + /** + * @ORM\Column(type="array", nullable=true) + */ + private $attributes = []; + + /** + * @ORM\Column(type="string", length=255, nullable=true) + */ + private $controller; + public function __construct() { $this->children = new ArrayCollection(); @@ -305,4 +320,48 @@ class Node implements EntityInterface return $this; } + + public function getParameters(): ?array + { + if (!is_array($this->parameters)) { + $this->parameters = []; + } + + return $this->parameters; + } + + public function setParameters(array $parameters): self + { + $this->parameters = $parameters; + + return $this; + } + + public function getAttributes(): ?array + { + if (!is_array($this->attributes)) { + $this->attributes = []; + } + + return $this->attributes; + } + + public function setAttributes(array $attributes): self + { + $this->attributes = $attributes; + + return $this; + } + + public function getController(): ?string + { + return $this->controller; + } + + public function setController(?string $controller): self + { + $this->controller = $controller; + + return $this; + } } diff --git a/core/Entity/Site/Page/Block.php b/core/Entity/Site/Page/Block.php index a92223c..5a21471 100644 --- a/core/Entity/Site/Page/Block.php +++ b/core/Entity/Site/Page/Block.php @@ -59,7 +59,7 @@ class Block return $this->value; } - public function setValue(string $value): self + public function setValue($value): self { $this->value = $value; diff --git a/core/EventSuscriber/Site/NodeEventSubscriber.php b/core/EventSuscriber/Site/NodeEventSubscriber.php index 95c2844..29e336d 100644 --- a/core/EventSuscriber/Site/NodeEventSubscriber.php +++ b/core/EventSuscriber/Site/NodeEventSubscriber.php @@ -11,6 +11,7 @@ use App\Core\Manager\EntityManager; use App\Core\Repository\Site\NodeRepository; use App\Core\Slugify\Slugify; use Symfony\Component\HttpKernel\KernelInterface; +use App\Core\Slugify\CodeSlugify; /** * class NodeEventSubscriber. @@ -23,17 +24,20 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber protected EntityManager $entityManager; protected KernelInterface $kernel; protected Slugify $slugify; + protected CodeSlugify $codeSlugify; public function __construct( NodeFactory $nodeFactory, NodeRepository $nodeRepository, EntityManager $entityManager, - Slugify $slugify + Slugify $slugify, + CodeSlugify $codeSlugify ) { $this->nodeFactory = $nodeFactory; $this->nodeRepository = $nodeRepository; $this->entityManager = $entityManager; $this->slugify = $slugify; + $this->codeSlugify = $codeSlugify; } public function support(EntityInterface $entity) @@ -49,6 +53,8 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber $node = $event->getEntity(); + $node->setCode($this->codeSlugify->slugify($node->getCode())); + if ($node->getUrl()) { $generatedUrl = $node->getUrl(); } else { @@ -68,6 +74,17 @@ class NodeEventSubscriber extends EntityManagerEventSubscriber $generatedUrl = '/'.implode('/', $path); } + $generatedUrl = rtrim($generatedUrl, '/'); + + foreach ($node->getParameters() as $parameter) { + $routeParameter = sprintf('{%s}', $parameter['name']); + $regex = '/'.preg_quote($routeParameter).'/'; + + if (!preg_match($regex, $generatedUrl)) { + $generatedUrl.= '/'.$routeParameter; + } + } + $urlExists = $this->nodeRepository->urlExists($generatedUrl, $node); if ($urlExists) { diff --git a/core/EventSuscriber/Site/Page/BlockEventSubscriber.php b/core/EventSuscriber/Site/Page/BlockEventSubscriber.php new file mode 100644 index 0000000..0564877 --- /dev/null +++ b/core/EventSuscriber/Site/Page/BlockEventSubscriber.php @@ -0,0 +1,58 @@ + + */ +class BlockEventSubscriber extends EntityManagerEventSubscriber +{ + protected FileUploadHandler $fileUpload; + + public function __construct(FileUploadHandler $fileUpload) + { + $this->fileUpload = $fileUpload; + } + + public function support(EntityInterface $entity) + { + return $entity instanceof Block; + } + + public function onPreUpdate(EntityManagerEvent $event) + { + if (!$this->support($event->getEntity())) { + return; + } + + $block = $event->getEntity(); + + if (!$block->getValue() instanceof UploadedFile) { + return; + } + + $directory = 'uploads/page/block'; + + $fileUpload->handleForm( + $block->getValue(), + $directory, + function ($filename) use ($block) { + $block->setValue($directory.'/'.$filename); + } + ); + } + + public function onPreCreate(EntityManagerEvent $event) + { + return $this->onPreUpdate($event); + } +} diff --git a/core/Form/Site/NodeAttributeType.php b/core/Form/Site/NodeAttributeType.php new file mode 100644 index 0000000..12ff3d5 --- /dev/null +++ b/core/Form/Site/NodeAttributeType.php @@ -0,0 +1,50 @@ +add( + 'label', + TextType::class, + [ + 'label' => 'Libellé', + 'required' => true, + 'attr' => [ + ], + 'constraints' => [ + new NotBlank(), + ], + ] + ); + + $builder->add( + 'value', + TextType::class, + [ + 'label' => 'Valeur', + 'required' => false, + 'attr' => [ + ], + 'constraints' => [ + ], + ] + ); + + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => null, + ]); + } +} diff --git a/core/Form/Site/NodeParameterType.php b/core/Form/Site/NodeParameterType.php new file mode 100644 index 0000000..6d9f487 --- /dev/null +++ b/core/Form/Site/NodeParameterType.php @@ -0,0 +1,62 @@ +add( + 'name', + TextType::class, + [ + 'label' => 'Nom', + 'required' => true, + 'attr' => [ + ], + 'constraints' => [ + new NotBlank(), + ], + ] + ); + + $builder->add( + 'defaultValue', + TextType::class, + [ + 'label' => 'Valeur par défaut', + 'required' => false, + 'attr' => [ + ], + 'constraints' => [ + ], + ] + ); + + $builder->add( + 'requirement', + TextType::class, + [ + 'label' => 'Éxigence', + 'required' => false, + 'attr' => [ + ], + 'constraints' => [ + ], + ] + ); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => null, + ]); + } +} diff --git a/core/Form/Site/NodeType.php b/core/Form/Site/NodeType.php index 6890928..a34c8f8 100644 --- a/core/Form/Site/NodeType.php +++ b/core/Form/Site/NodeType.php @@ -12,6 +12,7 @@ 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 Symfony\Component\Form\Extension\Core\Type\CollectionType; class NodeType extends AbstractType { @@ -59,6 +60,20 @@ class NodeType extends AbstractType ] ); + $builder->add( + 'controller', + TextType::class, + [ + 'label' => 'Contrôleur', + 'required' => false, + 'help' => 'Laisser vide pour utiliser celui par défaut. Notation : App\\Controller\\FooController::barAction', + 'attr' => [ + ], + 'constraints' => [ + ], + ] + ); + $actions = [ 'Nouvelle page' => 'new', 'Associer à une page existante' => 'existing', @@ -125,6 +140,30 @@ class NodeType extends AbstractType ] ); + $builder->add( + 'parameters', + CollectionType::class, + [ + 'entry_type' => NodeParameterType::class, + 'by_reference' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'prototype' => true, + ] + ); + + $builder->add( + 'attributes', + CollectionType::class, + [ + 'entry_type' => NodeAttributeType::class, + 'by_reference' => false, + 'allow_add' => true, + 'allow_delete' => true, + 'prototype' => true, + ] + ); + if (null === $builder->getData()->getId()) { $builder->add( 'position', diff --git a/core/Router/SiteRouteLoader.php b/core/Router/SiteRouteLoader.php index 8bd535c..1630276 100644 --- a/core/Router/SiteRouteLoader.php +++ b/core/Router/SiteRouteLoader.php @@ -42,13 +42,20 @@ class SiteRouteLoader extends Loader $requirements = []; $defaults = [ - '_controller' => PageController::class.'::show', + '_controller' => $node->getController() ?? PageController::class.'::show', '_node' => $node->getId(), '_menu' => $menu->getId(), '_page' => $node->getPage() ? $node->getPage()->getId() : null, '_navigation' => $navigation->getId(), ]; + foreach ($node->getParameters() as $parameter) { + $name = $parameter['name']; + + $requirements[$name] = $parameter['requirement']; + $defaults[$name] = $parameter['defaultValue']; + } + $route = new Route($node->getUrl(), $defaults, $requirements); $route->setHost($navigation->getDomain()); diff --git a/core/Slugify/CodeSlugify.php b/core/Slugify/CodeSlugify.php index 13236a7..1111dbc 100644 --- a/core/Slugify/CodeSlugify.php +++ b/core/Slugify/CodeSlugify.php @@ -11,6 +11,14 @@ use Cocur\Slugify\Slugify as BaseSlugify; */ class CodeSlugify extends Slugify { + public function slugify($data): ? string + { + $slug = parent::slugify($data); + $slug = preg_replace('/[^\w]+/', '', $slug); + + return $slug; + } + protected function create(): BaseSlugify { $slugify = new BaseSlugify([ @@ -19,7 +27,6 @@ class CodeSlugify extends Slugify ]); $slugify->activateRuleSet('french'); - $slugify->addRule("'", ''); return $slugify; } diff --git a/core/Slugify/Slugify.php b/core/Slugify/Slugify.php index 965a3ae..9985b2b 100644 --- a/core/Slugify/Slugify.php +++ b/core/Slugify/Slugify.php @@ -11,7 +11,7 @@ use Cocur\Slugify\Slugify as BaseSlugify; */ class Slugify { - public function slugify($data) + public function slugify($data): ?string { return $this->create()->slugify($data); } diff --git a/src/Controller/Blog/PostAdminController.php b/src/Controller/Blog/PostAdminController.php index b6d7fc7..0f880fb 100644 --- a/src/Controller/Blog/PostAdminController.php +++ b/src/Controller/Blog/PostAdminController.php @@ -69,11 +69,13 @@ class PostAdminController extends AdminController $form->handleRequest($request); if ($form->isValid()) { + $directory = 'uploads/post/'.date('Y'); + $fileUpload->handleForm( $form->get('image')->getData(), - 'uploads/post/'.date('Y'), + $directory, function ($filename) use ($entity) { - $entity->setImage('post/'.date('Y').'/'.$filename); + $entity->setImage($directory.'/'.$filename); } ); diff --git a/src/Entity/Page/SimplePage.php b/src/Entity/Page/SimplePage.php index 39c8727..4b6f846 100644 --- a/src/Entity/Page/SimplePage.php +++ b/src/Entity/Page/SimplePage.php @@ -4,10 +4,11 @@ namespace App\Entity\Page; use App\Core\Entity\Site\Page\Block; use App\Core\Entity\Site\Page\Page; -use App\Form\Site\Page\TextareaBlockType; -use App\Form\Site\Page\TextBlockType; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Form\FormBuilderInterface; +use App\Core\Form\Site\Page\FileBlockType; +use App\Core\Form\Site\Page\TextBlockType; +use App\Core\Form\Site\Page\TextareaBlockType; /** * @ORM\Entity @@ -44,6 +45,20 @@ class SimplePage extends Page ], ] ); + + // $builder->add( + // 'file', + // FileBlockType::class, + // [ + // 'label' => 'Fichier', + // 'options' => [ + // 'attr' => [ + // ], + // 'constraints' => [ + // ], + // ], + // ] + // ); } public function setTitle(Block $block) @@ -65,4 +80,14 @@ class SimplePage extends Page { return $this->getBlock('content'); } + + public function setFile(Block $block) + { + return $this->setBlock($block); + } + + public function getFile() + { + return $this->getBlock('file'); + } } diff --git a/templates/blog/post_admin/index.html.twig b/templates/blog/post_admin/index.html.twig index 4f4254b..03c06b5 100644 --- a/templates/blog/post_admin/index.html.twig +++ b/templates/blog/post_admin/index.html.twig @@ -37,7 +37,7 @@ {% if item.image %} - {% set image = asset('uploads/' ~ item.image) %} + {% set image = asset(item.image) %} {% else %} {% set image = asset('build/images/no-image.png') %} {% endif %} diff --git a/templates/blog/post_admin/show.html.twig b/templates/blog/post_admin/show.html.twig index 733e00f..1a6fd42 100644 --- a/templates/blog/post_admin/show.html.twig +++ b/templates/blog/post_admin/show.html.twig @@ -68,7 +68,7 @@ {% if entity.image %}
- {{ entity.imageCaption }} + {{ entity.imageCaption }}
{{ entity.imageCaption }} diff --git a/templates/site/node_admin/_form.html.twig b/templates/site/node_admin/_form.html.twig index a97a8e3..b8213cd 100644 --- a/templates/site/node_admin/_form.html.twig +++ b/templates/site/node_admin/_form.html.twig @@ -1,108 +1,248 @@ -{{ form_row(form.label) }} -{{ form_row(form.url) }} + -{% if form.position is defined %} - {{ form_row(form.position) }} -{% endif %} +
+
+ {{ form_row(form.label) }} -
-
- {% set action = form.pageAction[0] %} - {% set options = not entity.id ? {'attr': {'checked': 'checked'}} : {} %} + {% 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(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) }} +
+
+ {{ form_row(form.pageType) }}
-

-
-
-
- Aucune action
+
+ {% 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 %}
- {% endif %} +
+
+ {{ form_row(form.url) }} + +
+ Nom de la route : {{ entity.routeName }} +
+ + {{ form_row(form.code) }} + + {{ form_row(form.controller) }} + +
+ {% for item in form.parameters %} +
+
+ + {{ item.vars.data.name }} + +
+
+
+ {{ form_row(item.name) }} + {{ form_row(item.defaultValue) }} + {{ form_row(item.requirement) }} + +
+ + + +
+ + {{ form_rest(item) }} +
+
+
+ {% endfor %} +
+
+ + + Ajouter un paramètre + +
+
+
+
+ {% for item in form.attributes %} +
+
+ + {{ item.vars.data.label }} + +
+
+
+ {{ form_row(item.label) }} + {{ form_row(item.value) }} + +
+ + + +
+ + {{ form_rest(item) }} +
+
+
+ {% endfor %} +
+
+ + + Ajouter un attribut + +
+
+
+ + + + + +
+ {{ form_rest(form) }}
-{{ form_rest(form) }} diff --git a/templates/site/node_admin/edit.html.twig b/templates/site/node_admin/edit.html.twig index 4726266..598e586 100644 --- a/templates/site/node_admin/edit.html.twig +++ b/templates/site/node_admin/edit.html.twig @@ -10,10 +10,6 @@
{{ include('site/node_admin/_form.html.twig') }}
- -
- Nom de la route : {{ entity.routeName }} -