deblan.io-murph/src/Controller/Blog/PostController.php
Simon Vieille a572705b35
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/deployment/woodpecker Pipeline was successful
add preview
2023-04-02 18:52:31 +02:00

236 lines
7.7 KiB
PHP

<?php
namespace App\Controller\Blog;
use App\Core\Annotation\UrlGenerator;
use App\Core\Controller\Site\PageController;
use App\Core\Manager\EntityManager;
use App\Core\Site\SiteRequest;
use App\Core\Site\SiteStore;
use App\Entity\Blog\Category;
use App\Entity\Blog\Post;
use App\Factory\Blog\CommentFactory;
use App\Form\Blog\UserCommentType;
use App\Markdown\Parser\Post as PostParser;
use App\Repository\Blog\PostRepositoryQuery;
use App\UrlGenerator\PostGenerator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use App\Factory\Blog\PostFollowFactory;
use App\Manager\PostFollowManager;
use App\Core\Twig\Extension\EditorJsExtension;
class PostController extends PageController
{
protected PostRepositoryQuery $postQuery;
public function __construct(PostRepositoryQuery $postQuery, SiteRequest $siteRequest, SiteStore $siteStore)
{
parent::__construct($siteRequest, $siteStore);
$this->postQuery = $postQuery;
}
#[UrlGenerator(service: PostGenerator::class, method: 'post')]
public function post(
Post $post,
string $slug,
CommentFactory $commentFactory,
PostFollowManager $postFollowManager,
Request $request,
EntityManager $entityManager
): Response {
if (Post::DRAFT === $post->getStatus() && !$this->getUser()) {
throw $this->createNotFoundException();
}
if ($slug !== $post->getSlug()) {
return $this->redirectToRoute(
$this->siteRequest->getNode()->getRouteName(),
[
'post' => $post->getId(),
'slug' => $post->getSlug(),
]
);
}
$form = $this->createForm(UserCommentType::class, $commentFactory->create($post));
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$data = $request->request->get($form->getName());
$parentCommentId = (int) $data['parentCommentId'];
$follow = (bool) ($data['follow'] ?? false);
foreach ($post->getComments(['id' => $parentCommentId]) as $comment) {
$form->getData()->setParentComment($comment);
}
$entityManager->create($form->getData());
$this->addFlash('success', 'Commentaire publié !');
if ($follow && $form->getData()->getEmail()) {
$postFollowManager->create($post, $form->getData());
}
return $this->redirect($request->getUri());
}
$this->addFlash('error', 'Le formulaire n\'est pas valide.');
}
$similarPosts = $this->postQuery->getRepository()->findSimilarPosts($post, 3);
return $this->defaultRender($this->siteRequest->getPage()->getTemplate(), [
'post' => $post,
'similarPosts' => $similarPosts,
'form' => $form->createView(),
]);
}
public function posts(Request $request, int $page = 1): Response
{
$entities = $this->createQuery($request->query->has('preview') && $this->getUser())
->paginate($page, 9)
;
return $this->defaultRender($this->siteRequest->getPage()->getTemplate(), [
'pager' => $entities,
]);
}
public function search(Request $request, int $page = 1): Response
{
$query = $request->query->get('query');
$tag = $request->query->get('tag');
if ($query || $tag) {
$entities = $this->createQuery()
->search($query, $tag)
->paginate($page, 9)
;
}
return $this->defaultRender($this->siteRequest->getPage()->getTemplate(), [
'pager' => $entities ?? null,
'query' => $query,
]);
}
#[UrlGenerator(service: PostGenerator::class, method: 'category')]
public function category(Category $category, string $slug, int $page = 1): Response
{
$entities = $this->createQuery()
->inCategory($category, false)
->paginate($page, 9)
;
if (!$category->getIsActive() && !$this->getUser()) {
throw $this->createNotFoundException();
}
if ($slug !== $category->getSlug()) {
return $this->redirectToRoute(
$this->siteRequest->getNode()->getRouteName(),
[
'category' => $category->getId(),
'slug' => $category->getSlug(),
]
);
}
return $this->defaultRender($this->siteRequest->getPage()->getTemplate(), [
'category' => $category,
'pager' => $entities,
]);
}
public function tag(string $tag, int $page = 1): Response
{
}
public function createQuery(bool $isPreview = false): PostRepositoryQuery
{
$query = $this->postQuery->create()
->orderBy('.publishedAt', 'DESC');
if (!$isPreview) {
$query->published();
}
return $query;
}
public function rss(PostParser $parser, EditorJsExtension $editorJsExtension): Response
{
$entities = $this->createQuery()->paginate(1, 20);
$items = [];
foreach ($entities as $entity) {
if ($entity->getContentFormat() === 'editorjs') {
$description = $editorJsExtension->buildHtml($entity->getContent());
} else {
$description = $parser->transformMarkdown($entity->getContent());
}
$items[] = [
'title' => $entity->getTitle(),
'guid' => $entity->getId(),
'date' => $entity->getPublishedAt(),
'description' => $description,
'categories' => call_user_func(function () use ($entity) {
foreach ($entity->getCategories() as $category) {
if ($category->getIsActive()) {
yield $category->getTitle();
}
}
}),
'link' => $this->generateUrl('blog_menu_post', [
'post' => $entity->getId(),
'slug' => $entity->getSlug(),
], UrlGeneratorInterface::ABSOLUTE_URL),
'linkGemini' => sprintf('gemini://deblan.io/posts/%d.gmi', $entity->getId()),
];
}
$response = new Response();
$response->headers->set('Content-Type', 'text/xml');
return $this->defaultRender($this->siteRequest->getPage()->getTemplate(), [
'items' => $items,
], $response);
}
public function jsonApi(PostParser $parser): Response
{
$entities = $this->createQuery()->paginate(1, 30);
$items = [];
foreach ($entities as $entity) {
$items[] = [
'id' => $entity->getId(),
'title' => $entity->getTitle(),
'date' => $entity->getPublishedAt()->format('Y-m-d H:i:s'),
'link' => $this->generateUrl('blog_menu_post', [
'post' => $entity->getId(),
'slug' => $entity->getSlug(),
], UrlGeneratorInterface::ABSOLUTE_URL),
'content' => $entity->getContent(),
'categories' => call_user_func(function () use ($entity) {
foreach ($entity->getCategories() as $category) {
if ($category->getIsActive()) {
yield $category->getTitle();
}
}
}),
];
}
return $this->json($items);
}
}