diff --git a/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php b/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php index f97847a..7149cba 100644 --- a/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php +++ b/src/Domain/Manga/Application/CommandHandler/FetchMangaChaptersHandler.php @@ -52,20 +52,20 @@ readonly class FetchMangaChaptersHandler // Définir les règles de priorité des langues (fr > en > autres) $shouldReplaceChapter = false; - if (!isset($chaptersByNumber[$chapterNumber])) { + if (!isset($chaptersByNumber[(string) $chapterNumber])) { // Si c'est le premier chapitre avec ce numéro qu'on rencontre $shouldReplaceChapter = true; $chapterNumbers[] = $chapterNumber; } else if ($language === 'fr') { // Le français est toujours prioritaire $shouldReplaceChapter = true; - } else if ($language === 'en' && $chapterLanguages[$chapterNumber] !== 'fr') { + } else if ($language === 'en' && $chapterLanguages[(string) $chapterNumber] !== 'fr') { // L'anglais est prioritaire sur les autres langues, sauf le français $shouldReplaceChapter = true; } if ($shouldReplaceChapter) { - $chaptersByNumber[$chapterNumber] = new Chapter( + $chaptersByNumber[(string) $chapterNumber] = new Chapter( new ChapterId((string) Uuid::uuid4()), $manga->getId()->getValue(), $chapterNumber, @@ -75,7 +75,7 @@ readonly class FetchMangaChaptersHandler false, new \DateTimeImmutable() ); - $chapterLanguages[$chapterNumber] = $language; + $chapterLanguages[(string) $chapterNumber] = $language; } } @@ -94,7 +94,7 @@ readonly class FetchMangaChaptersHandler // Sauvegarde uniquement les nouveaux chapitres foreach ($chaptersByNumber as $chapterNumber => $chapter) { - if (!isset($existingChapters[$chapterNumber])) { + if (!isset($existingChapters[(float) $chapterNumber])) { $this->mangaRepository->saveChapter($chapter); } } diff --git a/src/Domain/Manga/Domain/Contract/Repository/MangaRepositoryInterface.php b/src/Domain/Manga/Domain/Contract/Repository/MangaRepositoryInterface.php index fc97771..6c1fea2 100644 --- a/src/Domain/Manga/Domain/Contract/Repository/MangaRepositoryInterface.php +++ b/src/Domain/Manga/Domain/Contract/Repository/MangaRepositoryInterface.php @@ -21,5 +21,9 @@ interface MangaRepositoryInterface public function findBySlug(MangaSlug $slug): ?Manga; public function search(string $query, int $page = 1, int $limit = 20): array; public function countSearch(string $query): int; + /** + * @param float[] $chapterNumbers + * @return array + */ public function findExistingChaptersByNumbers(string $mangaId, array $chapterNumbers): array; } diff --git a/src/Domain/Manga/Infrastructure/Persistence/LegacyMangaRepository.php b/src/Domain/Manga/Infrastructure/Persistence/LegacyMangaRepository.php index 61e450e..af5342e 100644 --- a/src/Domain/Manga/Infrastructure/Persistence/LegacyMangaRepository.php +++ b/src/Domain/Manga/Infrastructure/Persistence/LegacyMangaRepository.php @@ -200,6 +200,10 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface ->getSingleScalarResult(); } + /** + * @param float[] $chapterNumbers + * @return array + */ public function findExistingChaptersByNumbers(string $mangaId, array $chapterNumbers): array { $queryBuilder = $this->entityManager->createQueryBuilder() @@ -208,13 +212,13 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface ->where('c.manga = :mangaId') ->andWhere('c.number IN (:chapterNumbers)') ->setParameter('mangaId', $mangaId) - ->setParameter('chapterNumbers', $chapterNumbers); + ->setParameter('chapterNumbers', array_map('floatval', $chapterNumbers)); $chapters = $queryBuilder->getQuery()->getResult(); $chaptersByNumber = []; foreach ($chapters as $chapter) { - $chaptersByNumber[$chapter->getNumber()] = $this->toChapterDomain($chapter); + $chaptersByNumber[(float) $chapter->getNumber()] = $this->toChapterDomain($chapter); } return $chaptersByNumber; diff --git a/src/Domain/Scraping/Application/CommandHandler/ScrapeChapterHandler.php b/src/Domain/Scraping/Application/CommandHandler/ScrapeChapterHandler.php index bad3337..20f4357 100644 --- a/src/Domain/Scraping/Application/CommandHandler/ScrapeChapterHandler.php +++ b/src/Domain/Scraping/Application/CommandHandler/ScrapeChapterHandler.php @@ -11,6 +11,7 @@ use App\Domain\Scraping\Domain\Contract\Service\ImageDownloaderInterface; use App\Domain\Scraping\Domain\Contract\Service\ScraperInterface; use App\Domain\Scraping\Domain\Event\ChapterScraped; use App\Domain\Scraping\Domain\Event\ChapterScrapingFailed; +use App\Domain\Scraping\Domain\Model\Chapter; use App\Domain\Scraping\Domain\Model\ScrapingJob; use App\Domain\Scraping\Domain\Model\Source; use App\Domain\Scraping\Domain\Model\ValueObject\CbzGenerationRequest; @@ -41,6 +42,7 @@ readonly class ScrapeChapterHandler $job = null; try { // 1. Récupération du chapitre + /**@var Chapter $chapter */ $chapter = $this->chapterRepository->getById($command->chapterId); if (!$chapter) { throw new \InvalidArgumentException("Chapter not found with ID: {$command->chapterId}"); diff --git a/src/Domain/Scraping/Domain/Contract/Repository/ChapterRepositoryInterface.php b/src/Domain/Scraping/Domain/Contract/Repository/ChapterRepositoryInterface.php index cfd0591..73947f7 100644 --- a/src/Domain/Scraping/Domain/Contract/Repository/ChapterRepositoryInterface.php +++ b/src/Domain/Scraping/Domain/Contract/Repository/ChapterRepositoryInterface.php @@ -7,6 +7,9 @@ use App\Domain\Scraping\Domain\Model\Chapter; interface ChapterRepositoryInterface { public function getById(string $id): ?Chapter; - public function getByMangaIdAndChapterNumber(string $mangaId, int $chapterNumber): Chapter; + /** + * @throws ChapterNotFoundException + */ + public function getByMangaIdAndChapterNumber(string $mangaId, float $chapterNumber): Chapter; public function save(Chapter $chapter): void; } diff --git a/src/Domain/Scraping/Domain/Model/Chapter.php b/src/Domain/Scraping/Domain/Model/Chapter.php index 14199eb..bd854a3 100644 --- a/src/Domain/Scraping/Domain/Model/Chapter.php +++ b/src/Domain/Scraping/Domain/Model/Chapter.php @@ -7,8 +7,8 @@ class Chapter public function __construct( public readonly string $id, public readonly string $mangaId, - public readonly int $chapterNumber, - public readonly int $volumeNumber, - public ?string $cbzPath = null, + public readonly float $chapterNumber, + public readonly ?int $volumeNumber, + public ?string $cbzPath, ) {} } diff --git a/src/Domain/Scraping/Infrastructure/Persistence/LegacyChapterRepository.php b/src/Domain/Scraping/Infrastructure/Persistence/LegacyChapterRepository.php index 00c2f5e..97773b4 100644 --- a/src/Domain/Scraping/Infrastructure/Persistence/LegacyChapterRepository.php +++ b/src/Domain/Scraping/Infrastructure/Persistence/LegacyChapterRepository.php @@ -36,23 +36,23 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface /** * @throws ChapterNotFoundException */ - public function getByMangaIdAndChapterNumber(string $mangaId, int $chapterNumber): Chapter + public function getByMangaIdAndChapterNumber(string $mangaId, float $chapterNumber): Chapter { - $chapterEntity = $this->entityManager->getRepository(EntityChapter::class)->findOneBy([ + $entity = $this->entityManager->getRepository(EntityChapter::class)->findOneBy([ 'manga' => $mangaId, - 'number' => $chapterNumber, + 'number' => $chapterNumber ]); - if (!$chapterEntity) { + if ($entity === null) { throw new ChapterNotFoundException(); } return new Chapter( - id: $chapterEntity->getId(), - mangaId: $chapterEntity->getManga()->getId(), - chapterNumber: $chapterEntity->getNumber(), - volumeNumber: $chapterEntity->getVolume(), - cbzPath: $chapterEntity->getCbzPath(), + id: $entity->getId(), + mangaId: $entity->getManga()->getId(), + chapterNumber: $entity->getNumber(), + volumeNumber: $entity->getVolume(), + cbzPath: $entity->getCbzPath(), ); } diff --git a/tests/Domain/Scraping/Adapter/InMemoryChapterRepository.php b/tests/Domain/Scraping/Adapter/InMemoryChapterRepository.php index cf91f74..b0ec0cb 100644 --- a/tests/Domain/Scraping/Adapter/InMemoryChapterRepository.php +++ b/tests/Domain/Scraping/Adapter/InMemoryChapterRepository.php @@ -4,6 +4,7 @@ namespace App\Tests\Domain\Scraping\Adapter; use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface; use App\Domain\Scraping\Domain\Model\Chapter; +use App\Domain\Scraping\Domain\Exception\ChapterNotFoundException; class InMemoryChapterRepository implements ChapterRepositoryInterface { @@ -14,7 +15,7 @@ class InMemoryChapterRepository implements ChapterRepositoryInterface return $this->chapters[$id] ?? null; } - public function getByMangaIdAndChapterNumber(string $mangaId, int $chapterNumber): Chapter + public function getByMangaIdAndChapterNumber(string $mangaId, float $chapterNumber): Chapter { foreach ($this->chapters as $chapter) { if ($chapter->mangaId === $mangaId && $chapter->chapterNumber === $chapterNumber) { @@ -22,7 +23,7 @@ class InMemoryChapterRepository implements ChapterRepositoryInterface } } - throw new \RuntimeException('Chapter not found'); + throw new ChapterNotFoundException(); } public function save(Chapter $chapter): void