<?php
/**
* @author Antony Tkachenko <at@canaryknight.ru>
*/
namespace App\Controller;
use App\Entity\BlogPost;
use App\Entity\BlogTag;
use App\Repository\BlogPostRepository;
use App\Repository\BlogTagRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/blog", name="blog_")
*/
class BlogController extends AbstractController
{
private BlogPostRepository $blogPostRepository;
private BlogTagRepository $tagRepository;
private RequestStack $requestStack;
public function __construct(
BlogPostRepository $blogPostRepository,
BlogTagRepository $tagRepository,
RequestStack $requestStack
)
{
$this->blogPostRepository = $blogPostRepository;
$this->tagRepository = $tagRepository;
$this->requestStack = $requestStack;
}
private function getListTemplateName(): string
{
if ($this->requestStack->getMainRequest()->isMethod(Request::METHOD_POST)) {
return 'blog/index_content.html.twig';
}
return 'blog/index.html.twig';
}
private function getPageCount(?BlogTag $tag = NULL): int
{
$query = $this->blogPostRepository->onlyPublished(1, $tag);
return (int)ceil($query->select('count(b.id)')->setMaxResults(NULL)->setFirstResult(NULL)->getQuery()->getSingleScalarResult() / BlogPostRepository::PAGE_SIZE);
}
/**
* @return BlogPost[]
*/
private function findPosts(int $page = 1, ?BlogTag $tag = NULL): array
{
$query = $this->blogPostRepository->onlyPublished($page, $tag);
return $query->getQuery()->getResult();
}
private function lastModified(): ?\DateTimeInterface {
$query = $this->blogPostRepository->lastModified();
try {
$result = $query->getQuery()->getSingleResult();
if ($result && $result->getUpdatedAt()) {
return $result->getUpdatedAt();
}
} catch (NonUniqueResultException|NoResultException $e) {
}
return null;
}
/**
* @Route("/{page<\d+>}", name="index", methods={"GET", "POST"}, defaults={"page":1})
*/
public function index(int $page): Response
{
$date = $this->lastModified();
$modified = $date ? $date->format('D, d M Y H:i:s \G\M\T') : date('D, d M Y H:i:s \G\M\T');
$response = $this->render($this->getListTemplateName(), [
'tags' => $this->tagRepository->onlyActive(),
'posts' => $this->findPosts($page),
'current_page' => $page,
'next_page_url' => $this->generateUrl('blog_index', ['page' => $page + 1]),
'page_count' => $this->getPageCount(),
'current_tag' => NULL,
'modified' => $modified,
]);
$response->headers->set('Last-Modified', $modified);
return $response;
}
/**
* @Route("/tag/{slug}/{page<\d+>}", name="tag", methods={"GET"}, defaults={"page":1})
*/
public function tag(
int $page,
BlogTag $tag
): Response
{
$date = $this->lastModified();
$modified = $date ? $date->format('D, d M Y H:i:s \G\M\T') : date('D, d M Y H:i:s \G\M\T');
$response = $this->render($this->getListTemplateName(), [
'tags' => $this->tagRepository->onlyActive(),
'posts' => $this->findPosts($page, $tag),
'current_page' => $page,
'next_page_url' => $this->generateUrl('blog_index', ['page' => $page + 1]),
'page_count' => $this->getPageCount($tag),
'current_tag' => $tag->getId(),
'modified' => $modified,
]);
$response->headers->set('Last-Modified', $modified);
return $response;
}
/**
* @Route("/post/{slug}", name="post", methods={"GET"})
*/
public function post(BlogPost $post): Response
{
if (true !== $post->isPublished() && !$this->isGranted('ROLE_ADMIN')) {
throw new NotFoundHttpException();
}
$date = $post->getUpdatedAt() ?: $post->getCreatedAt();
$modified = $date->format('D, d M Y H:i:s \G\M\T');
$response = $this->render('blog/post.html.twig', [
'post' => $post,
'similar' => $this->blogPostRepository->findSimilar($post),
'tags' => $this->tagRepository->onlyActive(),
'title' => $post->getPageTitle(),
'description' => $post->getMetaDescription(),
'keywords' => $post->getMetaKeywords(),
'modified' => $modified,
]);
$response->headers->set('Last-Modified', $modified);
return $response;
}
}