add base of page CRUD

This commit is contained in:
Simon Vieille 2021-03-18 21:40:28 +01:00
parent 8a7e323501
commit b8335d3882
18 changed files with 765 additions and 2 deletions

View file

@ -423,3 +423,7 @@ table.table-fixed, .table-fixed > table {
}
}
}
fieldset.form-group {
margin-bottom: 0;
}

View file

@ -10,12 +10,17 @@ doctrine:
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
App\Entity:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
alias: App\Entity
App\Page:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Page'
prefix: 'App\Page'
gedmo_tree:
type: annotation
prefix: Gedmo\Tree\Entity

View file

@ -16,6 +16,9 @@ use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\TaggedContainerInterface;
/**
* @Route("/admin/site/node")

View file

@ -0,0 +1,84 @@
<?php
namespace App\Controller\Site;
use App\Controller\Admin\AdminController;
use App\Entity\Site\Page\Page as Entity;
use App\Factory\Site\Page\PageFactory as EntityFactory;
use App\Form\Site\Page\PageType as EntityType;
use App\Manager\EntityManager;
use App\Page\FooPage;
use App\Repository\Site\Page\PageRepositoryQuery as EntityRepositoryQuery;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Page\SimplePage;
/**
* @Route("/admin/site/page")
*/
class PageAdminController extends AdminController
{
/**
* @Route("/new", name="admin_site_page_new")
*/
public function new(EntityFactory $factory, EntityManager $entityManager): Response
{
// $entity = $factory->create(FooPage::class);
$entity = $factory->create(SimplePage::class);
$entity->setName('Page de test '.mt_rand());
$entityManager->create($entity);
$this->addFlash('success', 'Donnée enregistrée.');
return $this->redirectToRoute('admin_site_page_edit', [
'entity' => $entity->getId(),
]);
}
/**
* @Route("/edit/{entity}", name="admin_site_page_edit")
*/
public function edit(
int $entity,
EntityFactory $factory,
EntityManager $entityManager,
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);
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$entityManager->update($entity);
$this->addFlash('success', 'Donnée enregistrée.');
return $this->redirectToRoute('admin_site_page_edit', [
'entity' => $entity->getId(),
]);
}
$this->addFlash('warning', 'Le formulaire est invalide.');
}
return $this->render('site/page_admin/edit.html.twig', [
'form' => $form->createView(),
'entity' => $entity,
]);
}
public function getSection(): string
{
return '';
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace App\Entity\Site\Page;
use App\Repository\Site\Page\BlockRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Doctrine\Timestampable;
/**
* @ORM\Entity(repositoryClass=BlockRepository::class)
* @ORM\HasLifecycleCallbacks
*/
class Block
{
use Timestampable;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="text")
*/
private $value;
/**
* @ORM\ManyToOne(targetEntity=Page::class, inversedBy="blocks")
*/
private $page;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getPage(): ?Page
{
return $this->page;
}
public function setPage(?Page $page): self
{
$this->page = $page;
return $this;
}
}

View file

@ -0,0 +1,211 @@
<?php
namespace App\Entity\Site\Page;
use App\Doctrine\Timestampable;
use App\Repository\Site\Page\PageRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Form\FormBuilderInterface;
use App\Entity\EntityInterface;
/**
* @ORM\Entity(repositoryClass=PageRepository::class)
* @ORM\DiscriminatorColumn(name="class_key", type="string")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\HasLifecycleCallbacks
*/
class Page implements EntityInterface
{
use Timestampable;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $template;
/**
* @ORM\OneToMany(targetEntity=Block::class, mappedBy="page", cascade={"persist"})
*/
private $blocks;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $metaTitle;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $metaDescrition;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $ogTitle;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $ogDescription;
public function __construct()
{
$this->blocks = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getTemplate(): ?string
{
return $this->template;
}
public function setTemplate(?string $template): self
{
$this->template = $template;
return $this;
}
/**
* @return Collection|Block[]
*/
public function getBlocks(): Collection
{
return $this->blocks;
}
public function addBlock(Block $block): self
{
if (!$this->blocks->contains($block)) {
$this->blocks[] = $block;
$block->setPage($this);
}
return $this;
}
public function removeBlock(Block $block): self
{
if ($this->blocks->removeElement($block)) {
// set the owning side to null (unless already changed)
if ($block->getPage() === $this) {
$block->setPage(null);
}
}
return $this;
}
public function buildForm(FormBuilderInterface $builder)
{
}
public function getBlock($name)
{
foreach ($this->getBlocks() as $block) {
if ($block->getName() === $name) {
return $block;
}
}
$block = new Block();
$block->setName($name);
$block->setPage($this);
return $block;
}
public function setBlock(Block $block): self
{
foreach ($this->blocks->toArray() as $key => $value) {
if ($value->getName() === $block->getName()) {
$this->blocks->remove($key);
$this->blocks->add($block);
return $this;
}
}
$this->blocks->add($block);
return $this;
}
public function getMetaTitle(): ?string
{
return $this->metaTitle;
}
public function setMetaTitle(?string $metaTitle): self
{
$this->metaTitle = $metaTitle;
return $this;
}
public function getMetaDescrition(): ?string
{
return $this->metaDescrition;
}
public function setMetaDescrition(?string $metaDescrition): self
{
$this->metaDescrition = $metaDescrition;
return $this;
}
public function getOgTitle(): ?string
{
return $this->ogTitle;
}
public function setOgTitle(?string $ogTitle): self
{
$this->ogTitle = $ogTitle;
return $this;
}
public function getOgDescription(): ?string
{
return $this->ogDescription;
}
public function setOgDescription(?string $ogDescription): self
{
$this->ogDescription = $ogDescription;
return $this;
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace App\Factory\Site\Page;
use App\Entity\Site\Menu;
use App\Entity\Site\Navigation;
use App\Site\SimplePage;
use App\Entity\Site\Page\Page;
/**
* class PageFactory.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class PageFactory
{
public function create(string $className): Page
{
$entity = new $className();
return $entity;
}
}

View file

@ -67,6 +67,7 @@ class NodeType extends AbstractType
{
$resolver->setDefaults([
'data_class' => Node::class,
'pages' => null,
]);
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace App\Form\Site\Page;
use App\Entity\Site\Page\Page;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class PageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'metaTitle',
TextType::class,
[
'label' => 'Titre',
'required' => false,
'attr' => [
],
'constraints' => [
],
]
);
$builder->add(
'metaDescrition',
TextType::class,
[
'label' => 'Description',
'required' => false,
'attr' => [
],
'constraints' => [
],
]
);
$builder->add(
'ogTitle',
TextType::class,
[
'label' => 'Titre',
'required' => false,
'attr' => [
],
'constraints' => [
],
]
);
$builder->add(
'ogDescription',
TextType::class,
[
'label' => 'Description',
'required' => false,
'attr' => [
],
'constraints' => [
],
]
);
$builder->getData()->buildForm($builder);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Page::class,
]);
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace App\Form\Site\Page;
use App\Entity\Site\Page\Block;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class TextBlockType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'value',
TextType::class,
array_merge([
'required' => false,
'label' => false,
], $options['options']),
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Block::class,
'options' => [],
]);
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace App\Form\Site\Page;
use App\Entity\Site\Page\Block;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use App\Form\Site\Page\TextBlockType;
class TextareaBlockType extends TextBlockType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(
'value',
TextareaType::class,
array_merge([
'required' => false,
'label' => false,
], $options['options']),
);
}
}

70
src/Page/SimplePage.php Normal file
View file

@ -0,0 +1,70 @@
<?php
namespace App\Page;
use App\Entity\Site\Page\Block;
use App\Entity\Site\Page\Page;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use App\Form\Site\Page\TextareaBlockType;
use App\Form\Site\Page\TextBlockType;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SimplePage extends Page
{
public function buildForm(FormBuilderInterface $builder)
{
$builder->add(
'title',
TextBlockType::class,
[
'label' => 'Titre',
'required' => true,
'attr' => [
],
'constraints' => [
],
]
);
$builder->add(
'content',
TextareaBlockType::class,
[
'label' => 'Content',
'options' => [
'attr' => [
'data-tinymce' => '',
'rows' => '18',
],
'constraints' => [
],
]
]
);
}
public function setTitle(Block $block)
{
return $this->setBlock($block);
}
public function getTitle()
{
return $this->getBlock('title');
}
public function setContent(Block $block)
{
return $this->setBlock($block);
}
public function getContent()
{
return $this->getBlock('content');
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Repository\Site\Page;
use App\Entity\Site\Page\Block;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class BlockRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Block::class);
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Repository\Site\Page;
use App\Repository\RepositoryQuery;
use Knp\Component\Pager\PaginatorInterface;
/**
* class BlockRepositoryQuery.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class BlockRepositoryQuery extends RepositoryQuery
{
public function __construct(BlockRepository $repository, PaginatorInterface $paginator)
{
parent::__construct($repository, 'b', $paginator);
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Repository\Site\Page;
use App\Entity\Site\Page\Page;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class PageRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Page::class);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Repository\Site\Page;
use App\Repository\RepositoryQuery;
use Knp\Component\Pager\PaginatorInterface;
/**
* class PageRepositoryQuery.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class PageRepositoryQuery extends RepositoryQuery
{
public function __construct(PageRepository $repository, PaginatorInterface $paginator)
{
parent::__construct($repository, 'p', $paginator);
}
public function filterById($id)
{
$this
->where('.id = :id')
->setParameter(':id', $id);
return $this;
}
}

View file

@ -0,0 +1,40 @@
{% set formMetas %}
{% for item in ['metaTitle', 'metaDescrition'] %}
{{ form_row(form[item]) }}
{% endfor %}
{% endset %}
{% set formOpenGraph %}
{% for item in ['ogTitle', 'ogDescription'] %}
{{ form_row(form[item]) }}
{% endfor %}
{% endset %}
{% set formSitemap %}
{% endset %}
<div class="row">
<div class="col-8 p-2">
{{ form_widget(form) }}
</div>
<div class="col-4 p-3">
<ul class="nav nav-pills">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#form-page-metas">Métas</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#form-page-og">OpenGraph</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane show active p-3" id="form-page-metas">
{{ formMetas|raw }}
</div>
<div class="tab-pane p-3" id="form-page-og">
{{ formOpenGraph|raw }}
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,32 @@
{% extends 'admin/layout.html.twig' %}
{% block body %}
<div class="bg-light pl-5 pr-4 pt-5 pb-5">
<div class="d-flex">
<div class="mr-auto w-50">
<h1 class="display-5">{{ entity.name }}</h1>
</div>
<div class="ml-auto">
<div class="btn-group">
<button type="submit" form="form-main" class="btn btn-primary">
<span class="fa fa-save pr-1"></span>
Enregistrer
</button>
</div>
</div>
</div>
</div>
<form action="{{ app.request.uri }}" method="post" id="form-main" enctype="multipart/form-data">
<div class="tab-content">
<div class="tab-pane active">
<div class="tab-form">
{{ include('site/page_admin/_form.html.twig') }}
</div>
</div>
</div>
{{ form_rest(form) }}
</form>
{% endblock %}