feat(controller): add post lists controller

This commit is contained in:
2024-08-03 10:47:43 +02:00
parent 58f43f096a
commit a99f6244b4
32 changed files with 8956 additions and 447 deletions

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Controller;
class DetailPostController
{
}

View File

@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Repository\Post\PostRepository;
use App\Utils\Paginator\Paginator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
final class ListPostController extends AbstractController
{
public function __construct(
private readonly int $pageSize,
private readonly int $maxVisiblePages,
private readonly PostRepository $postRepository,
private readonly Paginator $paginator,
) {
}
#[Route('/', name: 'default')]
public function default(): Response
{
return $this->forward(ListPostController::class . '::pageList', ['page' => 1]);
}
#[Route('/posts/{page}', name: 'page_list', requirements: ['page' => '\d+'], defaults: ['page' => 1])]
public function pageList(int $page): Response
{
$totalPages = (int) ceil($this->postRepository->count([]) / $this->pageSize); /* TODO: tohle by si zaslouzilo asi cache */
if ($totalPages === 0) {
$this->logger->error('No posts found. Try run brilo:refresh-database command.');
throw new NotFoundHttpException('No posts found.');
}
if ($page === 0) {
return $this->redirectToRoute('page_list', ['page' => 1]);
}
// If page number is out of range, redirect to the last page.
if ($page > $totalPages) {
return $this->redirectToRoute('page_list', ['page' => $totalPages]);
}
$posts = $this->postRepository->getPaginatedPosts($page, $this->pageSize);
return $this->render('list_post/list.html.twig', [
'posts' => $posts,
'page' => $this->paginator->getVisiblePages($page, $totalPages, $this->maxVisiblePages),
]);
}
}

View File

@@ -18,4 +18,20 @@ class PostRepository extends ServiceEntityRepository
{
parent::__construct($registry, Post::class);
}
/**
* @param int $page
* @param int $pageSize
* @return array<Post>
*/
public function getPaginatedPosts(int $page, int $pageSize): array
{
$query = $this->createQueryBuilder('p')
->orderBy('p.id', 'DESC')
->setFirstResult(($page - 1) * $pageSize)
->setMaxResults($pageSize)
->getQuery();
return $query->getResult();
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\Utils\Paginator;
class Paginator
{
/**
* Determinate which pages are visible in the paginator
* @param int $page
* @param int $totalPages
* @param int $maxVisiblePages
* @return PaginatorResult
*/
public function getVisiblePages(int $page, int $totalPages, int $maxVisiblePages): PaginatorResult
{
$half = floor($maxVisiblePages / 2);
if ($page <= $half) {
$start = 1;
$end = min($totalPages, $maxVisiblePages);
} elseif ($page > $totalPages - $half) {
$start = max(1, $totalPages - $maxVisiblePages + 1);
$end = $totalPages;
} else {
$start = $page - $half;
$end = min($totalPages, $page + $half);
}
/**
* @var array<int> $range
*/
$range = range($start, $end);
return new PaginatorResult(
$page,
$start == 1,
$end == $totalPages,
$totalPages,
$totalPages,
$range
);
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace App\Utils\Paginator;
readonly class PaginatorResult
{
public function __construct(
public int $currentPage,
public bool $firstPageVisible,
public bool $lastPageVisible,
public int $totalPages,
public int $lastPage,
/**
* @var array<int>
*/
public array $visiblePages,
) {
}
}