feat: Reader beginning

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-02-16 16:15:42 +01:00
parent e90c0a140e
commit 55945adc53
37 changed files with 1057 additions and 47 deletions

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\Query;
final class GetChapterContext
{
public function __construct(
private readonly string $chapterId
) {
}
public function getChapterId(): string
{
return $this->chapterId;
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\Query;
final readonly class GetChapterPages
{
public function __construct(
private string $chapterId,
private int $page = 1,
private int $itemsPerPage = 20
) {
}
public function getChapterId(): string
{
return $this->chapterId;
}
public function getPage(): int
{
return $this->page;
}
public function getItemsPerPage(): int
{
return $this->itemsPerPage;
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\QueryHandler;
use App\Domain\Reader\Application\Query\GetChapterContext;
use App\Domain\Reader\Application\Response\ChapterContextResponse;
use App\Domain\Reader\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Reader\Domain\ValueObject\ChapterId;
final readonly class GetChapterContextHandler
{
public function __construct(
private ChapterRepositoryInterface $chapterRepository
) {
}
public function handle(GetChapterContext $query): ChapterContextResponse
{
$chapterId = new ChapterId($query->getChapterId());
$context = $this->chapterRepository->getChapterContext($chapterId);
return new ChapterContextResponse(
$query->getChapterId(),
$context->getChapterTitle(),
$context->getNumber(),
$context->getTotalPages(),
$context->getPreviousChapterId()?->getValue(),
$context->getNextChapterId()?->getValue(),
);
}
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\QueryHandler;
use App\Domain\Reader\Application\Query\GetChapterPages;
use App\Domain\Reader\Application\Response\ChapterPagesResponse;
use App\Domain\Reader\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Reader\Domain\Exception\ChapterNotFoundException;
use App\Domain\Reader\Domain\ValueObject\ChapterId;
final readonly class GetChapterPagesHandler
{
public function __construct(
private ChapterRepositoryInterface $chapterRepository
) {
}
public function handle(GetChapterPages $query): ChapterPagesResponse
{
$chapterId = new ChapterId($query->getChapterId());
$totalItems = $this->chapterRepository->getTotalPagesForChapter($chapterId);
if ($totalItems === 0) {
throw ChapterNotFoundException::forChapter($chapterId);
}
$pages = $this->chapterRepository->getPagesForChapter(
$chapterId,
$query->getPage(),
$query->getItemsPerPage()
);
return new ChapterPagesResponse(
$pages,
$totalItems,
$query->getPage(),
$query->getItemsPerPage()
);
}
}

View File

@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\Response;
final readonly class ChapterContextResponse
{
public function __construct(
private string $id,
private string $title,
private float $number,
private int $totalPages,
private ?string $previousChapterId,
private ?string $nextChapterId
)
{
}
public function getId(): string
{
return $this->id;
}
public function getTitle(): string
{
return $this->title;
}
public function getNumber(): float
{
return $this->number;
}
public function getTotalPages(): int
{
return $this->totalPages;
}
public function getPreviousChapterId(): ?string
{
return $this->previousChapterId;
}
public function getNextChapterId(): ?string
{
return $this->nextChapterId;
}
public function getNavigation(): array
{
$navigation['previousChapter'] = $this->previousChapterId;
$navigation['nextChapter'] = $this->nextChapterId;
return $navigation;
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\Response;
use App\Domain\Reader\Domain\Model\Page;
final class ChapterPagesResponse
{
/** @var array<PageResponse> */
private array $pages;
private int $totalItems;
private int $currentPage;
private int $itemsPerPage;
/**
* @param array<Page> $pages
*/
public function __construct(array $pages, int $totalItems, int $currentPage, int $itemsPerPage)
{
$this->pages = array_map(
static fn (Page $page) => new PageResponse($page),
$pages
);
$this->totalItems = $totalItems;
$this->currentPage = $currentPage;
$this->itemsPerPage = $itemsPerPage;
}
/**
* @return array<PageResponse>
*/
public function getPages(): array
{
return $this->pages;
}
public function getTotalItems(): int
{
return $this->totalItems;
}
public function getCurrentPage(): int
{
return $this->currentPage;
}
public function getItemsPerPage(): int
{
return $this->itemsPerPage;
}
public function getTotalPages(): int
{
return (int) ceil($this->totalItems / $this->itemsPerPage);
}
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Application\Response;
use App\Domain\Reader\Domain\Model\Page;
final class PageResponse
{
private string $id;
private int $pageNumber;
private string $url;
private array $dimensions;
public function __construct(Page $page)
{
$this->id = $page->getId();
$this->pageNumber = $page->getPageNumber()->getValue();
$this->url = $page->getUrl();
$this->dimensions = $page->getDimensions();
}
public function getId(): string
{
return $this->id;
}
public function getPageNumber(): int
{
return $this->pageNumber;
}
public function getUrl(): string
{
return $this->url;
}
public function getDimensions(): array
{
return $this->dimensions;
}
}