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,159 @@
<?php
declare(strict_types=1);
namespace App\Domain\Reader\Infrastructure\Persistence;
use App\Domain\Reader\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Reader\Domain\Exception\ChapterNotFoundException;
use App\Domain\Reader\Domain\Model\ChapterContext;
use App\Domain\Reader\Domain\Model\Page;
use App\Domain\Reader\Domain\ValueObject\ChapterId;
use App\Domain\Reader\Domain\ValueObject\PageNumber;
use App\Entity\Chapter as ChapterEntity;
use Doctrine\ORM\EntityManagerInterface;
use ZipArchive;
readonly class LegacyChapterRepository implements ChapterRepositoryInterface
{
public function __construct(
private EntityManagerInterface $entityManager
) {}
public function getPagesForChapter(ChapterId $chapterId, int $page = 1, int $itemsPerPage = 20): array
{
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
'id' => $chapterId->getValue()
]);
$cbzPath = $chapter->getCbzPath();
if (!$cbzPath) {
return [];
}
$zip = new ZipArchive();
$zip->open($cbzPath);
$pages = [];
$start = ($page - 1) * $itemsPerPage;
$end = min($start + $itemsPerPage, $zip->numFiles);
for ($i = $start; $i < $end; $i++) {
$stat = $zip->statIndex($i);
if ($stat === false) {
continue;
}
$imageContent = $zip->getFromIndex($i);
if ($imageContent === false) {
continue;
}
$imageSize = @getimagesizefromstring($imageContent);
if ($imageSize === false) {
continue;
}
$pages[] = new Page(
$stat['name'],
new PageNumber($i + 1),
sprintf('/api/chapters/%s/pages/%d', $chapterId->getValue(), $i + 1),
$imageSize[0],
$imageSize[1]
);
}
$zip->close();
return $pages;
}
public function getChapterContext(ChapterId $chapterId): ChapterContext
{
/** @var ChapterEntity $chapter */
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
'id' => $chapterId->getValue()
]);
if (!$chapter) {
throw ChapterNotFoundException::forChapter($chapterId);
}
return new ChapterContext(
id: $chapterId,
previousChapterId: $this->getPreviousChapterId($chapterId),
nextChapterId: $this->getNextChapterId($chapterId),
mangaTitle: $chapter->getManga()->getTitle(),
number: $chapter->getNumber(),
chapterTitle: $chapter->getTitle(),
cbzPath: $chapter->getCbzPath(),
volume: $chapter->getVolume(),
totalPages: 0,
isVisible: $chapter->isVisible(),
createdAt: new \DateTimeImmutable()
);
}
public function getTotalPagesForChapter(ChapterId $chapterId): int
{
$chapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
'id' => $chapterId->getValue()
]);
$cbzPath = $chapter->getCbzPath();
if (!$cbzPath) {
return 0;
}
$zip = new ZipArchive();
$zip->open($cbzPath);
return $zip->numFiles;
}
public function getPreviousChapterId(ChapterId $chapterId): ?ChapterId
{
$currentChapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
'id' => $chapterId->getValue()
]);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('c')
->from(ChapterEntity::class, 'c')
->where('c.manga = :manga')
->andWhere('c.number < :number')
->orderBy('c.number', 'DESC')
->setMaxResults(1)
->setParameters([
'manga' => $currentChapter->getManga(),
'number' => $currentChapter->getNumber()
]);
$previousChapter = $qb->getQuery()->getOneOrNullResult();
return $previousChapter ? new ChapterId((string) $previousChapter->getId()) : null;
}
public function getNextChapterId(ChapterId $chapterId): ?ChapterId
{
$currentChapter = $this->entityManager->getRepository(ChapterEntity::class)->findOneBy([
'id' => $chapterId->getValue()
]);
$qb = $this->entityManager->createQueryBuilder();
$qb->select('c')
->from(ChapterEntity::class, 'c')
->where('c.manga = :manga')
->andWhere('c.number > :number')
->orderBy('c.number', 'ASC')
->setMaxResults(1)
->setParameters([
'manga' => $currentChapter->getManga(),
'number' => $currentChapter->getNumber()
]);
$nextChapter = $qb->getQuery()->getOneOrNullResult();
return $nextChapter ? new ChapterId((string) $nextChapter->getId()) : null;
}
}