add blog entities; add repository query logic

This commit is contained in:
Simon Vieille 2021-03-16 16:46:39 +01:00
parent 2ce9de08ff
commit 40782e56ab
15 changed files with 699 additions and 2 deletions

View file

@ -0,0 +1,27 @@
<?php
namespace App\Controller\Blog;
use App\Controller\Admin\AdminController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/admin/blog/category")
*/
class CategoryAdminController extends AdminController
{
/**
* @Route("/", name="admin_blog_category_index")
*/
public function index(): Response
{
return $this->render('blog/category_admin/index.html.twig', [
]);
}
public function getSection(): string
{
return 'blog_category';
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace App\Controller\Blog;
use App\Controller\Admin\AdminController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/admin/blog/post")
*/
class PostAdminController extends AdminController
{
/**
* @Route("/", name="admin_blog_post_index")
*/
public function index(): Response
{
return $this->render('blog/post_admin/index.html.twig', [
]);
}
public function getSection(): string
{
return 'blog_post';
}
}

View file

@ -0,0 +1,57 @@
<?php
namespace App\Doctrine;
trait Timestampable
{
/**
* @ORM\Column(name="created_at", type="datetime")
*/
protected $createdAt;
/**
* @ORM\Column(name="updated_at", type="datetime")
*/
protected $updatedAt;
/**
* @ORM\PrePersist
*/
public function onPrePersist(): void
{
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
/**
* @ORM\PreUpdate
*/
public function onPreUpdate(): void
{
$this->updatedAt = new \DateTime();
}
public function setCreatedAt(?\DateTime $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getCreatedAt():?\DateTime
{
return $this->createdAt;
}
public function setUpdatedAt(?\DateTime $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getUpdatedAt():?\DateTime
{
return $this->updatedAt;
}
}

View file

@ -0,0 +1,92 @@
<?php
namespace App\Entity\Blog;
use App\Repository\Blog\CategoryRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=CategoryRepository::class)
*/
class Category
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $subTitle;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $slug;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getSubTitle(): ?string
{
return $this->subTitle;
}
public function setSubTitle(?string $subTitle): self
{
$this->subTitle = $subTitle;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(?string $slug): self
{
$this->slug = $slug;
return $this;
}
}

198
src/Entity/Blog/Post.php Normal file
View file

@ -0,0 +1,198 @@
<?php
namespace App\Entity\Blog;
use App\Entity\User;
use App\Repository\Blog\PostRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Doctrine\Timestampable;
/**
* @ORM\Entity(repositoryClass=PostRepository::class)
*/
class Post
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $subTitle;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $content;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $metaDescription;
/**
* @ORM\Column(type="integer")
*/
private $status;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $image;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $slug;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $publishedAt;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $imageCaption;
/**
* @ORM\ManyToOne(targetEntity=User::class, inversedBy="posts")
*/
private $author;
use Timestampable;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getSubTitle(): ?string
{
return $this->subTitle;
}
public function setSubTitle(?string $subTitle): self
{
$this->subTitle = $subTitle;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(?string $content): self
{
$this->content = $content;
return $this;
}
public function getMetaDescription(): ?string
{
return $this->metaDescription;
}
public function setMetaDescription(?string $metaDescription): self
{
$this->metaDescription = $metaDescription;
return $this;
}
public function getStatus(): ?int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
public function getImage(): ?string
{
return $this->image;
}
public function setImage(?string $image): self
{
$this->image = $image;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(?string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getPublishedAt(): ?\DateTimeInterface
{
return $this->publishedAt;
}
public function setPublishedAt(?\DateTimeInterface $publishedAt): self
{
$this->publishedAt = $publishedAt;
return $this;
}
public function getImageCaption(): ?string
{
return $this->imageCaption;
}
public function setImageCaption(?string $imageCaption): self
{
$this->imageCaption = $imageCaption;
return $this;
}
public function getAuthor(): ?User
{
return $this->author;
}
public function setAuthor(?User $author): self
{
$this->author = $author;
return $this;
}
}

View file

@ -2,11 +2,15 @@
namespace App\Entity;
use App\Entity\Blog\Post;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface;
use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Doctrine\Timestampable;
/**
* @ORM\Entity(repositoryClass=UserRepository::class)
@ -62,6 +66,18 @@ class User implements UserInterface, TwoFactorInterface, Entity
*/
private $isAdmin;
/**
* @ORM\OneToMany(targetEntity=Post::class, mappedBy="author")
*/
private $posts;
public function __construct()
{
$this->posts = new ArrayCollection();
}
use Timestampable;
public function getId(): ?int
{
return $this->id;
@ -241,4 +257,34 @@ class User implements UserInterface, TwoFactorInterface, Entity
return $this;
}
/**
* @return Collection|Post[]
*/
public function getPosts(): Collection
{
return $this->posts;
}
public function addPost(Post $post): self
{
if (!$this->posts->contains($post)) {
$this->posts[] = $post;
$post->setAuthor($this);
}
return $this;
}
public function removePost(Post $post): self
{
if ($this->posts->removeElement($post)) {
// set the owning side to null (unless already changed)
if ($post->getAuthor() === $this) {
$post->setAuthor(null);
}
}
return $this;
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace App\Repository\Blog;
use App\Entity\Blog\Category;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Category|null find($id, $lockMode = null, $lockVersion = null)
* @method Category|null findOneBy(array $criteria, array $orderBy = null)
* @method Category[] findAll()
* @method Category[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CategoryRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Category::class);
}
// /**
// * @return Category[] Returns an array of Category objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('c')
->andWhere('c.exampleField = :val')
->setParameter('val', $value)
->orderBy('c.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Category
{
return $this->createQueryBuilder('c')
->andWhere('c.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}

View file

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

View file

@ -0,0 +1,50 @@
<?php
namespace App\Repository\Blog;
use App\Entity\Blog\Post;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Post|null find($id, $lockMode = null, $lockVersion = null)
* @method Post|null findOneBy(array $criteria, array $orderBy = null)
* @method Post[] findAll()
* @method Post[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PostRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Post::class);
}
// /**
// * @return Post[] Returns an array of Post objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('p')
->andWhere('p.exampleField = :val')
->setParameter('val', $value)
->orderBy('p.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Post
{
return $this->createQueryBuilder('p')
->andWhere('p.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}

View file

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

View file

@ -0,0 +1,90 @@
<?php
namespace App\Repository;
use App\Criteria\CriteriaMap;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\QueryBuilder;
use Knp\Component\Pager\PaginatorInterface;
/**
* class RepositoryQuery.
*
* @author Simon Vieille <simon@deblan.fr>
*/
abstract class RepositoryQuery
{
protected ServiceEntityRepository $repository;
protected QueryBuilder $query;
protected PaginatorInterface $paginator;
protected string $id;
public function __construct(ServiceEntityRepository $repository, string $id, PaginatorInterface $paginator = null)
{
$this->repository = $repository;
$this->query = $repository->createQueryBuilder($id);
$this->paginator = $paginator;
$this->id = $id;
}
public function create()
{
$class = get_called_class();
return new $class($this->repository, $this->paginator);
}
public function __call(string $name, $params): self
{
$fn = function(&$data) {
if (is_string($data)) {
$words = explode(' ', $data);
foreach ($words as $k => $v) {
if (isset($v[0]) && $v[0] === '.') {
$words[$k] = $this->id.$v;
}
}
$data = implode(' ', $words);
} else {
foreach ($data as $k => $v) {
$fn($data[$k]);
}
}
return $data;
};
foreach ($params as $key => $value)
{
$fn($params[$key]);
}
call_user_func_array([$this->query, $name], $params);
return $this;
}
public function call(callable $fn): self
{
$fn($this->query, $this);
return $this;
}
public function findOne()
{
return $this->query->getQuery()->getOneOrNullResult();
}
public function find()
{
return $this->query->getQuery()->getResult();
}
public function paginate(int $page = 1, int $limit = 20)
{
return $this->paginator->paginate($this->query->getQuery(), $page, $limit);
}
}

View file

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

View file

@ -64,7 +64,7 @@
</li>
<li class="nav-item">
<a class="nav-link {{ macros.active_class('blog_post', section) }}" href="{{ path('admin_dashboard_index') }}">
<a class="nav-link {{ macros.active_class('blog_post', section) }}" href="{{ path('admin_blog_post_index') }}">
<span class="fa fa-pen"></span>
<span class="nav-item-label">Articles</span>
@ -72,7 +72,7 @@
</li>
<li class="nav-item">
<a class="nav-link {{ macros.active_class('blog_post', section) }}" href="{{ path('admin_dashboard_index') }}">
<a class="nav-link {{ macros.active_class('blog_category', section) }}" href="{{ path('admin_blog_category_index') }}">
<span class="fa fa-puzzle-piece"></span>
<span class="nav-item-label">Catégories</span>

View file

@ -0,0 +1 @@
{% extends 'admin/layout.html.twig' %}

View file

@ -0,0 +1 @@
{% extends 'admin/layout.html.twig' %}