add node ang page edition
This commit is contained in:
parent
023e6aec06
commit
237b105289
|
@ -17,4 +17,5 @@ return [
|
||||||
Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
|
Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
|
||||||
Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
|
Scheb\TwoFactorBundle\SchebTwoFactorBundle::class => ['all' => true],
|
||||||
Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
|
Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true],
|
||||||
|
App\Bundle\AppBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
|
8
config/packages/app.yaml
Normal file
8
config/packages/app.yaml
Normal file
|
@ -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"}
|
|
@ -16,11 +16,11 @@ doctrine:
|
||||||
dir: '%kernel.project_dir%/src/Entity'
|
dir: '%kernel.project_dir%/src/Entity'
|
||||||
prefix: 'App\Entity'
|
prefix: 'App\Entity'
|
||||||
alias: App\Entity
|
alias: App\Entity
|
||||||
App\Page:
|
App\Site\Page:
|
||||||
is_bundle: false
|
is_bundle: false
|
||||||
type: annotation
|
type: annotation
|
||||||
dir: '%kernel.project_dir%/src/Page'
|
dir: '%kernel.project_dir%/src/Site/Page'
|
||||||
prefix: 'App\Page'
|
prefix: 'App\Site\Page'
|
||||||
gedmo_tree:
|
gedmo_tree:
|
||||||
type: annotation
|
type: annotation
|
||||||
prefix: Gedmo\Tree\Entity
|
prefix: Gedmo\Tree\Entity
|
||||||
|
|
24
src/Bundle/AppBundle.php
Normal file
24
src/Bundle/AppBundle.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Twig.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Bundle;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
use App\DependencyInjection\AppExtension;
|
||||||
|
|
||||||
|
class AppBundle extends Bundle
|
||||||
|
{
|
||||||
|
public function getContainerExtension()
|
||||||
|
{
|
||||||
|
return new AppExtension();
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,9 @@ use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use App\Site\PageLocator;
|
||||||
|
use App\Factory\Site\Page\PageFactory;
|
||||||
|
use App\Entity\Site\Page\Page;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/admin/site/node")
|
* @Route("/admin/site/node")
|
||||||
|
@ -28,12 +31,16 @@ class NodeAdminController extends AdminController
|
||||||
public function new(
|
public function new(
|
||||||
Node $node,
|
Node $node,
|
||||||
EntityFactory $factory,
|
EntityFactory $factory,
|
||||||
|
PageFactory $pageFactory,
|
||||||
EntityManager $entityManager,
|
EntityManager $entityManager,
|
||||||
NodeRepository $nodeRepository,
|
NodeRepository $nodeRepository,
|
||||||
|
PageLocator $pageLocator,
|
||||||
Request $request
|
Request $request
|
||||||
): Response {
|
): Response {
|
||||||
$entity = $factory->create($node->getMenu());
|
$entity = $factory->create($node->getMenu());
|
||||||
$form = $this->createForm(EntityType::class, $entity);
|
$form = $this->createForm(EntityType::class, $entity, [
|
||||||
|
'pages' => $pageLocator->getPages(),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($request->isMethod('POST')) {
|
if ($request->isMethod('POST')) {
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
@ -46,17 +53,24 @@ class NodeAdminController extends AdminController
|
||||||
|
|
||||||
if ('above' === $position) {
|
if ('above' === $position) {
|
||||||
$nodeRepository->persistAsLastChild($entity, $node);
|
$nodeRepository->persistAsLastChild($entity, $node);
|
||||||
$entityManager->flush();
|
|
||||||
} else {
|
} else {
|
||||||
if ('after' === $position) {
|
if ('after' === $position) {
|
||||||
$nodeRepository->persistAsNextSiblingOf($entity, $node);
|
$nodeRepository->persistAsNextSiblingOf($entity, $node);
|
||||||
} elseif ('before' === $position) {
|
} elseif ('before' === $position) {
|
||||||
$nodeRepository->persistAsPrevSiblingOf($entity, $node);
|
$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.');
|
$this->addFlash('success', 'Donnée enregistrée.');
|
||||||
} else {
|
} else {
|
||||||
$this->addFlash('warning', 'Le formulaire est invalide.');
|
$this->addFlash('warning', 'Le formulaire est invalide.');
|
||||||
|
@ -77,13 +91,29 @@ class NodeAdminController extends AdminController
|
||||||
/**
|
/**
|
||||||
* @Route("/edit/{entity}", name="admin_site_node_edit")
|
* @Route("/edit/{entity}", name="admin_site_node_edit")
|
||||||
*/
|
*/
|
||||||
public function edit(Entity $entity, EntityManager $entityManager, Request $request): Response {
|
public function edit(
|
||||||
$form = $this->createForm(EntityType::class, $entity);
|
Entity $entity,
|
||||||
|
EntityManager $entityManager,
|
||||||
|
PageFactory $pageFactory,
|
||||||
|
PageLocator $pageLocator,
|
||||||
|
Request $request
|
||||||
|
): Response {
|
||||||
|
$form = $this->createForm(EntityType::class, $entity, [
|
||||||
|
'pages' => $pageLocator->getPages(),
|
||||||
|
]);
|
||||||
|
|
||||||
if ($request->isMethod('POST')) {
|
if ($request->isMethod('POST')) {
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
|
$this->handlePageAssociation(
|
||||||
|
$form->get('pageAction')->getData(),
|
||||||
|
$form->get('pageEntity')->getData(),
|
||||||
|
$form->get('pageType')->getData(),
|
||||||
|
$entity,
|
||||||
|
$pageFactory
|
||||||
|
);
|
||||||
|
|
||||||
$entityManager->update($entity);
|
$entityManager->update($entity);
|
||||||
|
|
||||||
$this->addFlash('success', 'Donnée enregistrée.');
|
$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")
|
* @Route("/move/{entity}", name="admin_site_node_move")
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -47,11 +47,6 @@ class PageAdminController extends AdminController
|
||||||
EntityRepositoryQuery $repositoryQuery,
|
EntityRepositoryQuery $repositoryQuery,
|
||||||
Request $request
|
Request $request
|
||||||
): Response {
|
): Response {
|
||||||
// $page = $factory->create(PageFoo::class);
|
|
||||||
// $page->setName('Page de test 2');
|
|
||||||
// $entityManager->update($page);
|
|
||||||
// die;
|
|
||||||
|
|
||||||
$entity = $repositoryQuery->filterById($entity)->findOne();
|
$entity = $repositoryQuery->filterById($entity)->findOne();
|
||||||
$form = $this->createForm(EntityType::class, $entity);
|
$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
|
public function getSection(): string
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
|
|
29
src/DependencyInjection/AppExtension.php
Normal file
29
src/DependencyInjection/AppExtension.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||||
|
use App\DependencyInjection\Configuration;
|
||||||
|
|
||||||
|
class AppExtension extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
$configuration = $this->getConfiguration($configs, $container);
|
||||||
|
$config = $this->processConfiguration($configuration, $configs);
|
||||||
|
|
||||||
|
$container->setParameter('app', $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getConfiguration(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
return new Configuration();
|
||||||
|
}
|
||||||
|
}
|
44
src/DependencyInjection/Configuration.php
Normal file
44
src/DependencyInjection/Configuration.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||||
|
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||||
|
|
||||||
|
class Configuration implements ConfigurationInterface
|
||||||
|
{
|
||||||
|
public function getConfigTreeBuilder(): TreeBuilder
|
||||||
|
{
|
||||||
|
$treeBuilder = new TreeBuilder('app');
|
||||||
|
|
||||||
|
$treeBuilder->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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ namespace App\Entity\Site;
|
||||||
|
|
||||||
use App\Doctrine\Timestampable;
|
use App\Doctrine\Timestampable;
|
||||||
use App\Entity\EntityInterface;
|
use App\Entity\EntityInterface;
|
||||||
|
use App\Entity\Site\Page\Page;
|
||||||
use App\Repository\Site\NodeRepository;
|
use App\Repository\Site\NodeRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
@ -85,6 +86,12 @@ class Node implements EntityInterface
|
||||||
*/
|
*/
|
||||||
private $children;
|
private $children;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Page::class, inversedBy="nodes", cascade={"persist"})
|
||||||
|
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||||
|
*/
|
||||||
|
private $page;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->children = new ArrayCollection();
|
$this->children = new ArrayCollection();
|
||||||
|
@ -260,4 +267,16 @@ class Node implements EntityInterface
|
||||||
|
|
||||||
return trim($prefix.' '.$this->getLabel());
|
return trim($prefix.' '.$this->getLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPage(): ?Page
|
||||||
|
{
|
||||||
|
return $this->page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPage(?Page $page): self
|
||||||
|
{
|
||||||
|
$this->page = $page;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ class Block
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Page::class, inversedBy="blocks")
|
* @ORM\ManyToOne(targetEntity=Page::class, inversedBy="blocks")
|
||||||
|
* @ORM\JoinColumn(onDelete="CASCADE")
|
||||||
*/
|
*/
|
||||||
private $page;
|
private $page;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Entity\Site\Page;
|
||||||
|
|
||||||
use App\Doctrine\Timestampable;
|
use App\Doctrine\Timestampable;
|
||||||
use App\Entity\EntityInterface;
|
use App\Entity\EntityInterface;
|
||||||
|
use App\Entity\Site\Node;
|
||||||
use App\Repository\Site\Page\PageRepository;
|
use App\Repository\Site\Page\PageRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
@ -62,9 +63,15 @@ class Page implements EntityInterface
|
||||||
*/
|
*/
|
||||||
private $ogDescription;
|
private $ogDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToMany(targetEntity=Node::class, mappedBy="page")
|
||||||
|
*/
|
||||||
|
private $nodes;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->blocks = new ArrayCollection();
|
$this->blocks = new ArrayCollection();
|
||||||
|
$this->nodes = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
|
@ -208,4 +215,34 @@ class Page implements EntityInterface
|
||||||
|
|
||||||
return $this;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,11 @@ use App\Entity\Site\Page\Page;
|
||||||
*/
|
*/
|
||||||
class PageFactory
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
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
|
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) {
|
if ($builder->getData()->getId() === null) {
|
||||||
$builder->add(
|
$builder->add(
|
||||||
'position',
|
'position',
|
||||||
|
@ -69,7 +139,7 @@ class NodeType extends AbstractType
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'data_class' => Node::class,
|
'data_class' => Node::class,
|
||||||
'pages' => null,
|
'pages' => [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,26 @@ use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||||
|
|
||||||
class PageType extends AbstractType
|
class PageType extends AbstractType
|
||||||
{
|
{
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
|
$builder->add(
|
||||||
|
'name',
|
||||||
|
TextType::class,
|
||||||
|
[
|
||||||
|
'label' => 'Nom',
|
||||||
|
'required' => true,
|
||||||
|
'attr' => [
|
||||||
|
],
|
||||||
|
'constraints' => [
|
||||||
|
new NotBlank(),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$builder->add(
|
$builder->add(
|
||||||
'metaTitle',
|
'metaTitle',
|
||||||
TextType::class,
|
TextType::class,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Page;
|
namespace App\Site\Page;
|
||||||
|
|
||||||
use App\Entity\Site\Page\Block;
|
use App\Entity\Site\Page\Block;
|
||||||
use App\Entity\Site\Page\Page;
|
use App\Entity\Site\Page\Page;
|
51
src/Site/PageConfiguration.php
Normal file
51
src/Site/PageConfiguration.php
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Site;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class PageConfiguration.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
48
src/Site/PageLocator.php
Normal file
48
src/Site/PageLocator.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Site;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class PageLocator.
|
||||||
|
*
|
||||||
|
* @author Simon Vieille <simon@deblan.fr>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
108
templates/site/node_admin/_form.html.twig
Normal file
108
templates/site/node_admin/_form.html.twig
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
{{ form_row(form.label) }}
|
||||||
|
{{ form_row(form.url) }}
|
||||||
|
|
||||||
|
{% if form.position is defined %}
|
||||||
|
{{ form_row(form.position) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="accordion" id="node-page-action">
|
||||||
|
<div class="card">
|
||||||
|
{% set action = form.pageAction[0] %}
|
||||||
|
{% set options = not entity.id ? {'attr': {'checked': 'checked'}} : {} %}
|
||||||
|
|
||||||
|
<div class="card-header p-0">
|
||||||
|
<h2 class="mb-0">
|
||||||
|
<label class="btn btn-link btn-block text-left"
|
||||||
|
for="{{ action.vars.id }}"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#form-node-page-action-new">
|
||||||
|
{{ action.vars.label }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="d-none">
|
||||||
|
{{ form_row(action, options) }}
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="form-node-page-action-new" class="collapse {% if not entity.id %}show{% endif %}" data-parent="#node-page-action">
|
||||||
|
<div class="card-body">
|
||||||
|
{{ form_row(form.pageType) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
{% set action = form.pageAction[1] %}
|
||||||
|
|
||||||
|
<div class="card-header p-0">
|
||||||
|
<h2 class="mb-0">
|
||||||
|
<label class="btn btn-link btn-block text-left"
|
||||||
|
for="{{ action.vars.id }}"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#form-node-page-action-existing">
|
||||||
|
{{ action.vars.label }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="d-none">
|
||||||
|
{{ form_row(action) }}
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="form-node-page-action-existing" class="collapse" data-parent="#node-page-action">
|
||||||
|
<div class="card-body">
|
||||||
|
{{ form_row(form.pageEntity) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
{% set action = form.pageAction[2] %}
|
||||||
|
|
||||||
|
<div class="card-header p-0">
|
||||||
|
<h2 class="mb-0">
|
||||||
|
<label class="btn btn-link btn-block text-left"
|
||||||
|
for="{{ action.vars.id }}"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#form-node-page-action-none">
|
||||||
|
{{ action.vars.label }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="d-none">
|
||||||
|
{{ form_row(action) }}
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="form-node-page-action-none" class="collapse" data-parent="#node-page-action">
|
||||||
|
<div class="card-body">
|
||||||
|
Aucune action
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if entity.id %}
|
||||||
|
<div class="card">
|
||||||
|
{% set action = form.pageAction[3] %}
|
||||||
|
{% set options = {'attr': {'checked': 'checked'}} %}
|
||||||
|
|
||||||
|
<div class="card-header p-0">
|
||||||
|
<h2 class="mb-0">
|
||||||
|
<label class="btn btn-link btn-block text-left"
|
||||||
|
for="{{ action.vars.id }}"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#form-node-page-action-keep">
|
||||||
|
{{ action.vars.label }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="d-none">
|
||||||
|
{{ form_row(action, options) }}
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="form-node-page-action-keep" class="collapse show" data-parent="#node-page-action">
|
||||||
|
<div class="card-body">
|
||||||
|
Aucune action
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ form_rest(form) }}
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form action="{{ path('admin_site_node_edit', {entity: entity.id}) }}" id="form-node-edit" method="POST">
|
<form action="{{ path('admin_site_node_edit', {entity: entity.id}) }}" id="form-node-edit" method="POST">
|
||||||
{{ form_widget(form) }}
|
{{ include('site/node_admin/_form.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form action="{{ path('admin_site_node_new', {node: node.id}) }}" id="form-node-new" method="POST">
|
<form action="{{ path('admin_site_node_new', {node: node.id}) }}" id="form-node-new" method="POST">
|
||||||
{{ form_widget(form) }}
|
{{ include('site/node_admin/_form.html.twig') }}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endset %}
|
{% endset %}
|
||||||
|
|
||||||
|
{% set formOthers %}
|
||||||
|
{% for item in ['name'] %}
|
||||||
|
{{ form_row(form[item]) }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endset %}
|
||||||
|
|
||||||
{% set formSitemap %}
|
{% set formSitemap %}
|
||||||
{% endset %}
|
{% endset %}
|
||||||
|
|
||||||
|
@ -25,6 +31,9 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" data-toggle="tab" href="#form-page-og">OpenGraph</a>
|
<a class="nav-link" data-toggle="tab" href="#form-page-og">OpenGraph</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" data-toggle="tab" href="#form-page-others">Autres</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
@ -34,7 +43,9 @@
|
||||||
<div class="tab-pane p-3" id="form-page-og">
|
<div class="tab-pane p-3" id="form-page-og">
|
||||||
{{ formOpenGraph|raw }}
|
{{ formOpenGraph|raw }}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-pane p-3" id="form-page-others">
|
||||||
|
{{ formOthers|raw }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
<span class="fa fa-save pr-1"></span>
|
<span class="fa fa-save pr-1"></span>
|
||||||
Enregistrer
|
Enregistrer
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-white dropdown-toggle dropdown-toggle-hide-after" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="font-weight-bold">
|
||||||
|
⋅⋅⋅
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<button type="submit" form="form-delete" class="dropdown-item">
|
||||||
|
Supprimer
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,4 +40,9 @@
|
||||||
|
|
||||||
{{ form_rest(form) }}
|
{{ form_rest(form) }}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form method="post" action="{{ path('admin_site_page_delete', {entity: entity.id}) }}" id="form-delete" data-form-confirm>
|
||||||
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ entity.id) }}">
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -70,30 +70,42 @@
|
||||||
{% set move = path('admin_site_node_move', {entity: node.id}) %}
|
{% set move = path('admin_site_node_move', {entity: node.id}) %}
|
||||||
{% set edit = path('admin_site_node_edit', {entity: node.id}) %}
|
{% set edit = path('admin_site_node_edit', {entity: node.id}) %}
|
||||||
{% set new = path('admin_site_node_new', {node: node.id}) %}
|
{% set new = path('admin_site_node_new', {node: node.id}) %}
|
||||||
|
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="float-right">
|
<div class="float-right">
|
||||||
|
{% if node.page %}
|
||||||
|
<a href="{{ path('admin_site_page_edit', {entity: node.page.id}) }}" class="btn btn-sm btn-warning text-white mr-1">
|
||||||
|
<span class="fa fa-file-alt"></span>
|
||||||
|
Page
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<button data-modal="{{ edit }}" type="submit" class="btn btn-sm btn-success mr-1">
|
<button data-modal="{{ edit }}" type="submit" class="btn btn-sm btn-success mr-1">
|
||||||
<span data-modal="{{ edit }}" class="fa fa-pen"></span>
|
<span data-modal="{{ edit }}" class="fa fa-pen"></span>
|
||||||
</button>
|
Éditer
|
||||||
|
|
||||||
<button data-modal="{{ move }}" type="submit" class="btn btn-sm btn-dark mr-1">
|
|
||||||
<span data-modal="{{ move }}" class="fa fa-arrows-alt"></span>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="submit" form="form-node-visibility-{{ node.id }}" class="btn btn-sm btn-light border-dark mr-1">
|
<button type="submit" form="form-node-visibility-{{ node.id }}" class="btn btn-sm btn-light border-dark mr-1">
|
||||||
{% if node.isVisible %}
|
{% if node.isVisible %}
|
||||||
<span class="fa fa-eye"></span>
|
<span class="fa fa-eye"></span>
|
||||||
|
Visible
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="fa fa-eye-slash"></span>
|
<span class="fa fa-eye-slash"></span>
|
||||||
|
Caché
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button data-modal="{{ move }}" type="submit" class="btn btn-sm btn-dark mr-1">
|
||||||
|
<span data-modal="{{ move }}" class="fa fa-arrows-alt"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button data-modal="{{ new }}" type="submit" class="btn btn-sm btn-primary mr-1">
|
<button data-modal="{{ new }}" type="submit" class="btn btn-sm btn-primary mr-1">
|
||||||
<span data-modal="{{ new }}" class="fa fa-plus"></span>
|
<span data-modal="{{ new }}" class="fa fa-plus"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="submit" form="form-node-delete-{{ node.id }}" class="btn btn-sm btn-danger">
|
<button type="submit" form="form-node-delete-{{ node.id }}" class="btn btn-sm btn-danger">
|
||||||
<span class="fa fa-trash"></span>
|
<span class="fa fa-trash"></span>
|
||||||
|
Supprimer
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue