Le domaine Scraping ne génère plus d'archives CBZ ni ne modifie les
entités du domaine Manga directement. Il scrape, stocke les images
individuellement, et émet un événement partagé.
- Suppression : CbzGeneratorInterface, CbzGenerator, CbzGenerationRequest,
CbzPath, CbzGenerationException
- Suppression : save() de ChapterRepositoryInterface (Scraping)
- Suppression : cbzPath du modèle Chapter (Scraping)
- Ajout : ImageStorageInterface + LocalImageStorage
(stockage dans {MANGA_DATA_PATH}/pages/{chapterId}/)
- ScrapeChapterHandler utilise ImageStorage au lieu du générateur CBZ
- ChapterScraped déplacé dans Domain/Shared/Domain/Event/
avec jobId, chapterId, pagesDirectory, pageCount
- Routing Messenger ajouté
- Ajout : ChapterScrapedEventListener + ChapterScrapedMessageHandler
pour mettre à jour Chapter.pagesDirectory via le Repository Manga
- LegacyChapterRepository en dual-mode :
pagesDirectory en priorité, fallback cbzPath (backward compat)
- Requêtes prev/next : filtrent pagesDirectory IS NOT NULL OR cbzPath IS NOT NULL
- ChapterContext expose pagesDirectory
- phparkitect.php : App\Domain\Shared\Domain\Event autorisé dans
les couches Application (correction violations pré-existantes
ChapterImported/VolumeImported + nouvelle ChapterScraped)
- 218/218 tests passent (+3 nouveaux)
- InMemoryImageStorage créé pour les tests unitaires
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
1.6 KiB
PHP
56 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace App\Domain\Scraping\Infrastructure\Persistence;
|
|
|
|
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
|
|
use App\Domain\Scraping\Domain\Exception\ChapterNotFoundException;
|
|
use App\Domain\Scraping\Domain\Model\Chapter;
|
|
use App\Entity\Chapter as EntityChapter;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
|
{
|
|
public function __construct(
|
|
private EntityManagerInterface $entityManager,
|
|
) {
|
|
}
|
|
|
|
public function getById(string $id): ?Chapter
|
|
{
|
|
$chapterEntity = $this->entityManager->getRepository(EntityChapter::class)->find($id);
|
|
|
|
if (!$chapterEntity) {
|
|
return null;
|
|
}
|
|
|
|
return new Chapter(
|
|
id: $chapterEntity->getId(),
|
|
mangaId: $chapterEntity->getManga()->getId(),
|
|
chapterNumber: $chapterEntity->getNumber(),
|
|
volumeNumber: $chapterEntity->getVolume(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @throws ChapterNotFoundException
|
|
*/
|
|
public function getByMangaIdAndChapterNumber(string $mangaId, float $chapterNumber): Chapter
|
|
{
|
|
$entity = $this->entityManager->getRepository(EntityChapter::class)->findOneBy([
|
|
'manga' => $mangaId,
|
|
'number' => $chapterNumber
|
|
]);
|
|
|
|
if ($entity === null) {
|
|
throw new ChapterNotFoundException();
|
|
}
|
|
|
|
return new Chapter(
|
|
id: $entity->getId(),
|
|
mangaId: $entity->getManga()->getId(),
|
|
chapterNumber: $entity->getNumber(),
|
|
volumeNumber: $entity->getVolume(),
|
|
);
|
|
}
|
|
}
|