refactor(manga): Chapter entité DDD de Manga + AggregateRoot
- Ajoute AggregateRoot dans Shared (domain events + pull pattern) - Manga extends AggregateRoot, devient vrai aggregate root DDD - Chapter passe de readonly à entité mutable avec MangaId VO - Manga expose les méthodes domaine pour toute mutation de chapitre : addChapter, updateChapterTitle/Volume/Pages, hideChapter, removeChapterPages - Supprime saveChapter/updateChapter/deleteChapter de MangaRepositoryInterface - save(Manga) gère désormais la persistance des chapitres via pull pattern - Tous les handlers/listeners passent par l'agrégat (plus d'accès direct) - phparkitect autorise AggregateRoot dans les couches Domain Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a4b3d8a5f1
commit
2c051351a8
@@ -115,6 +115,44 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
|
||||
if ($entity->getId()) {
|
||||
$manga->updateId(new MangaId((string) $entity->getId()));
|
||||
}
|
||||
|
||||
// Handle new chapters added through the aggregate
|
||||
foreach ($manga->pullNewChapters() as $chapter) {
|
||||
$mangaEntity = $this->entityManager->find(EntityManga::class, (int) $manga->getId()->getValue());
|
||||
$chapterEntity = new EntityChapter();
|
||||
$chapterEntity->setManga($mangaEntity)
|
||||
->setNumber($chapter->getNumber())
|
||||
->setTitle($chapter->getTitle())
|
||||
->setVolume($chapter->getVolume())
|
||||
->setVisible($chapter->isVisible())
|
||||
->setPagesDirectory($chapter->getPagesDirectory())
|
||||
->setPageCount($chapter->getPageCount());
|
||||
$this->entityManager->persist($chapterEntity);
|
||||
}
|
||||
|
||||
// Handle chapters modified through the aggregate
|
||||
foreach ($manga->pullModifiedChapters() as $chapter) {
|
||||
$chapterEntity = $this->entityManager->find(EntityChapter::class, $chapter->getId());
|
||||
if ($chapterEntity) {
|
||||
$chapterEntity->setVisible($chapter->isVisible())
|
||||
->setPagesDirectory($chapter->getPagesDirectory())
|
||||
->setPageCount($chapter->getPageCount())
|
||||
->setTitle($chapter->getTitle())
|
||||
->setVolume($chapter->getVolume())
|
||||
->setCbzPath($chapter->getPagesDirectory());
|
||||
$this->entityManager->persist($chapterEntity);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle chapters deleted through the aggregate
|
||||
foreach ($manga->pullChaptersToDelete() as $chapter) {
|
||||
$chapterEntity = $this->entityManager->find(EntityChapter::class, $chapter->getId());
|
||||
if ($chapterEntity) {
|
||||
$this->entityManager->remove($chapterEntity);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
public function delete(DomainManga $manga): void
|
||||
@@ -166,29 +204,6 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
|
||||
return $entity ? $this->toDomain($entity) : null;
|
||||
}
|
||||
|
||||
public function saveChapter(Chapter $chapter): ChapterId
|
||||
{
|
||||
$manga = $this->entityManager->find(EntityManga::class, $chapter->getMangaId());
|
||||
|
||||
if (!$manga) {
|
||||
throw new \RuntimeException('Manga not found');
|
||||
}
|
||||
|
||||
$entity = new EntityChapter();
|
||||
$entity->setManga($manga)
|
||||
->setNumber($chapter->getNumber())
|
||||
->setTitle($chapter->getTitle())
|
||||
->setVolume($chapter->getVolume())
|
||||
->setVisible($chapter->isVisible())
|
||||
->setPagesDirectory($chapter->getPagesDirectory())
|
||||
->setPageCount($chapter->getPageCount());
|
||||
|
||||
$this->entityManager->persist($entity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new ChapterId((string) $entity->getId());
|
||||
}
|
||||
|
||||
public function findChapterById(string $id): ?Chapter
|
||||
{
|
||||
$entity = $this->entityManager->find(EntityChapter::class, $id);
|
||||
@@ -226,36 +241,6 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
|
||||
return $entity ? $this->toChapterDomain($entity) : null;
|
||||
}
|
||||
|
||||
public function updateChapter(Chapter $chapter): void
|
||||
{
|
||||
$entity = $this->entityManager->find(EntityChapter::class, $chapter->getId());
|
||||
|
||||
if (!$entity) {
|
||||
throw new \RuntimeException(sprintf('Chapter with id %s not found', $chapter->getId()));
|
||||
}
|
||||
|
||||
$entity->setVisible($chapter->isVisible())
|
||||
->setPagesDirectory($chapter->getPagesDirectory())
|
||||
->setPageCount($chapter->getPageCount())
|
||||
->setTitle($chapter->getTitle())
|
||||
->setVolume($chapter->getVolume())
|
||||
// Keep cbzPath in sync during transition (Phase 4 will drop this column)
|
||||
->setCbzPath($chapter->getPagesDirectory());
|
||||
|
||||
$this->entityManager->persist($entity);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
public function deleteChapter(Chapter $chapter): void
|
||||
{
|
||||
$entity = $this->entityManager->find(EntityChapter::class, $chapter->getId());
|
||||
|
||||
if ($entity) {
|
||||
$this->entityManager->remove($entity);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function findChaptersByMangaIdAndVolume(string $mangaId, int $volume): array
|
||||
{
|
||||
$entities = $this->entityManager->getRepository(EntityChapter::class)
|
||||
@@ -417,7 +402,7 @@ readonly class LegacyMangaRepository implements MangaRepositoryInterface
|
||||
{
|
||||
return new Chapter(
|
||||
id: new ChapterId((string) $entity->getId()),
|
||||
mangaId: (string) $entity->getManga()->getId(),
|
||||
mangaId: new MangaId((string) $entity->getManga()->getId()),
|
||||
number: $entity->getNumber(),
|
||||
title: $entity->getTitle(),
|
||||
volume: $entity->getVolume(),
|
||||
|
||||
Reference in New Issue
Block a user