refactor(scraping): DDD refactoring — stockage images individuelles

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é.

## Changements principaux

### Domaine Scraping
- 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

### Événement partagé
- ChapterScraped déplacé dans Domain/Shared/Domain/Event/
  avec jobId, chapterId, pagesDirectory, pageCount
- Routing Messenger ajouté

### Domaine Manga
- Ajout : ChapterScrapedEventListener + ChapterScrapedMessageHandler
  pour mettre à jour Chapter.pagesDirectory via le Repository Manga

### Domaine Reader
- 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

### Architecture
- phparkitect.php : App\Domain\Shared\Domain\Event autorisé dans
  les couches Application (correction violations pré-existantes
  ChapterImported/VolumeImported + nouvelle ChapterScraped)

## Tests
- 218/218 tests passent (+3 nouveaux)
- InMemoryImageStorage créé pour les tests unitaires

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2026-03-09 20:44:10 +01:00
parent 640d1cec82
commit b7f4ee9082
26 changed files with 480 additions and 336 deletions

View File

@@ -36,6 +36,7 @@ framework:
'App\Domain\Manga\Domain\Event\MangaCreated': events
'App\Domain\Shared\Domain\Event\ChapterImported': events
'App\Domain\Shared\Domain\Event\VolumeImported': events
'App\Domain\Shared\Domain\Event\ChapterScraped': events
# Legacy messages (à garder si nécessaire)
'App\Message\DownloadChapter': commands

View File

@@ -126,7 +126,12 @@ services:
tags:
- { name: messenger.message_handler, bus: command.bus }
App\Domain\Scraping\Infrastructure\Service\CbzGenerator: ~
App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface:
alias: App\Domain\Scraping\Infrastructure\Service\LocalImageStorage
App\Domain\Scraping\Infrastructure\Service\LocalImageStorage:
arguments:
$storagePath: '%env(MANGA_DATA_PATH)%'
# Shared Manga Path/File Manager
App\Domain\Shared\Domain\Contract\MangaPathManagerInterface:

View File

@@ -12,10 +12,8 @@ services:
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryScrapingJobRepository'
public: true
App\Domain\Scraping\Domain\Contract\Service\CbzGeneratorInterface:
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryCbzGenerator'
arguments:
$projectDir: '%kernel.project_dir%'
App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface:
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryImageStorage'
public: true
App\Domain\Manga\Domain\Contract\Service\ImageProcessorInterface: