1 Commits

Author SHA1 Message Date
ext.jeremy.guillot@maxicoffee.domains
b7f4ee9082 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>
2026-03-09 20:44:10 +01:00
227 changed files with 353 additions and 432 deletions

View File

@@ -15,7 +15,7 @@ class SecurityController extends AbstractController
#[Route('/login', name: 'app_login', methods: ['GET', 'POST'])] #[Route('/login', name: 'app_login', methods: ['GET', 'POST'])]
public function login(IriConverterInterface $iriConverter, #[CurrentUser] User $user = null): Response public function login(IriConverterInterface $iriConverter, #[CurrentUser] User $user = null): Response
{ {
if (!$user) { if(!$user) {
return $this->json([ return $this->json([
'error' => 'Invalid credentials' 'error' => 'Invalid credentials'
], 401); ], 401);

View File

@@ -8,6 +8,7 @@ use App\Form\ContentSourceType;
use App\Manager\AppSettingsManager; use App\Manager\AppSettingsManager;
use App\Manager\Toolbar\Factory\ToolbarFactory; use App\Manager\Toolbar\Factory\ToolbarFactory;
use App\Repository\ContentSourceRepository; use App\Repository\ContentSourceRepository;
use App\Service\NotificationService; use App\Service\NotificationService;
use App\Service\Scraper\MangaScraperService; use App\Service\Scraper\MangaScraperService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;

View File

@@ -46,7 +46,7 @@ class TestController extends AbstractController
$changed = 0; $changed = 0;
foreach ($mangas as $manga) { foreach ($mangas as $manga) {
//si getImageUrl() retourne un lien sous la forme d'une URL (https ou http) //si getImageUrl() retourne un lien sous la forme d'une URL (https ou http)
if ($manga->getImageUrl()) { if($manga->getImageUrl()) {
$imageUrls = $this->processAndSaveImage($manga->getImageUrl()); $imageUrls = $this->processAndSaveImage($manga->getImageUrl());
$manga->setThumbnailUrl($imageUrls['thumbnail']); $manga->setThumbnailUrl($imageUrls['thumbnail']);
$this->mangaRepository->save($manga, true); $this->mangaRepository->save($manga, true);

View File

@@ -8,6 +8,5 @@ final readonly class ConvertFileCommand
public string $filePath, public string $filePath,
public string $originalFilename, public string $originalFilename,
public int $fileSize public int $fileSize
) { ) {}
}
} }

View File

@@ -14,8 +14,7 @@ final readonly class ConvertFileCommandHandler
public function __construct( public function __construct(
private ConversionServiceInterface $conversionService private ConversionServiceInterface $conversionService
) { ) {}
}
public function handle(ConvertFileCommand $command): ConversionResponse public function handle(ConvertFileCommand $command): ConversionResponse
{ {

View File

@@ -11,8 +11,7 @@ final readonly class ConversionResponse
public string $outputFilename, public string $outputFilename,
public int $originalFileSize, public int $originalFileSize,
public int $convertedFileSize public int $convertedFileSize
) { ) {}
}
public static function fromConversionResult(ConversionResult $result): self public static function fromConversionResult(ConversionResult $result): self
{ {

View File

@@ -8,8 +8,7 @@ final readonly class ConversionRequest
private string $filePath, private string $filePath,
private string $originalFilename, private string $originalFilename,
private int $fileSize private int $fileSize
) { ) {}
}
public function getFilePath(): string public function getFilePath(): string
{ {

View File

@@ -9,8 +9,7 @@ final readonly class ConversionResult
private string $outputFilename, private string $outputFilename,
private int $originalFileSize, private int $originalFileSize,
private int $convertedFileSize private int $convertedFileSize
) { ) {}
}
public function getConvertedFilePath(): string public function getConvertedFilePath(): string
{ {

View File

@@ -17,8 +17,7 @@ final class ConvertFileController extends AbstractController
{ {
public function __construct( public function __construct(
private readonly ConvertFileCommandHandler $commandHandler private readonly ConvertFileCommandHandler $commandHandler
) { ) {}
}
public function __invoke(Request $request): Response public function __invoke(Request $request): Response
{ {

View File

@@ -8,6 +8,5 @@ readonly class ChapterEditData
public string $id, public string $id,
public ?string $title = null, public ?string $title = null,
public ?int $volume = null public ?int $volume = null
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class CheckMonitoredMangas
{ {
public function __construct( public function __construct(
public ?DateTimeImmutable $since = null public ?DateTimeImmutable $since = null
) { ) {}
}
} }

View File

@@ -15,6 +15,5 @@ readonly class CreateManga
public ?string $externalId, public ?string $externalId,
public ?string $imageUrl, public ?string $imageUrl,
public ?float $rating public ?float $rating
) { ) {}
} }
}

View File

@@ -6,6 +6,5 @@ readonly class CreateMangaFromMangadex
{ {
public function __construct( public function __construct(
public string $externalId public string $externalId
) { ) {}
} }
}

View File

@@ -8,6 +8,5 @@ readonly class DeleteCbz implements CommandInterface
{ {
public function __construct( public function __construct(
public string $chapterId public string $chapterId
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class DeleteChapter implements CommandInterface
{ {
public function __construct( public function __construct(
public string $chapterId public string $chapterId
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class DeleteManga implements CommandInterface
{ {
public function __construct( public function __construct(
public string $mangaId public string $mangaId
) { ) {}
}
} }

View File

@@ -14,6 +14,5 @@ readonly class EditManga
public ?string $status = null, public ?string $status = null,
public ?float $rating = null, public ?float $rating = null,
public ?array $alternativeSlugs = null public ?array $alternativeSlugs = null
) { ) {}
}
} }

View File

@@ -9,6 +9,5 @@ readonly class EditMultipleChapters
*/ */
public function __construct( public function __construct(
public array $chapters public array $chapters
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class FetchMangaChapters
{ {
public function __construct( public function __construct(
public MangaId $mangaId public MangaId $mangaId
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class ImportChapter
public string $mangaId, public string $mangaId,
public float $chapterNumber, public float $chapterNumber,
public string $fileBinary public string $fileBinary
) { ) {}
}
} }

View File

@@ -8,6 +8,9 @@ readonly class ImportVolume
public string $mangaId, public string $mangaId,
public int $volumeNumber, public int $volumeNumber,
public string $fileBinary public string $fileBinary
) { ) {}
}
} }

View File

@@ -8,6 +8,5 @@ readonly class RefreshMangaChapters
{ {
public function __construct( public function __construct(
public MangaId $mangaId public MangaId $mangaId
) { ) {}
}
} }

View File

@@ -9,6 +9,5 @@ readonly class ToggleMangaMonitoring
public function __construct( public function __construct(
public MangaId $mangaId, public MangaId $mangaId,
public bool $enabled public bool $enabled
) { ) {}
}
} }

View File

@@ -14,8 +14,7 @@ readonly class CheckMonitoredMangasHandler
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private MessageBusInterface $commandBus private MessageBusInterface $commandBus
) { ) {}
}
public function handle(CheckMonitoredMangas $command): void public function handle(CheckMonitoredMangas $command): void
{ {

View File

@@ -20,8 +20,7 @@ readonly class CreateMangaFromMangadexHandler
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private ImageProcessorInterface $imageProcessor, private ImageProcessorInterface $imageProcessor,
private EventDispatcherInterface $eventDispatcher private EventDispatcherInterface $eventDispatcher
) { ) {}
}
public function handle(CreateMangaFromMangadex $command): void public function handle(CreateMangaFromMangadex $command): void
{ {

View File

@@ -21,8 +21,7 @@ readonly class CreateMangaHandler
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private ImageProcessorInterface $imageProcessor, private ImageProcessorInterface $imageProcessor,
private MessageBusInterface $messageBus private MessageBusInterface $messageBus
) { ) {}
}
public function handle(CreateManga $command): void public function handle(CreateManga $command): void
{ {

View File

@@ -15,8 +15,7 @@ readonly class DeleteCbzHandler implements CommandHandlerInterface
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private FileServiceInterface $fileService private FileServiceInterface $fileService
) { ) {}
}
public function handle(CommandInterface $command): void public function handle(CommandInterface $command): void
{ {

View File

@@ -12,8 +12,7 @@ readonly class DeleteChapterHandler implements CommandHandlerInterface
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(CommandInterface $command): void public function handle(CommandInterface $command): void
{ {

View File

@@ -12,8 +12,7 @@ readonly class DeleteMangaHandler implements CommandHandlerInterface
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(CommandInterface $command): void public function handle(CommandInterface $command): void
{ {

View File

@@ -11,8 +11,7 @@ readonly class EditMangaHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(EditManga $command): void public function handle(EditManga $command): void
{ {

View File

@@ -10,8 +10,7 @@ readonly class EditMultipleChaptersHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(EditMultipleChapters $command): void public function handle(EditMultipleChapters $command): void
{ {

View File

@@ -13,8 +13,7 @@ readonly class FetchMangaChaptersHandler
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private ChapterSynchronizationServiceInterface $chapterSynchronizationService private ChapterSynchronizationServiceInterface $chapterSynchronizationService
) { ) {}
}
public function handle(FetchMangaChapters $command): void public function handle(FetchMangaChapters $command): void
{ {
@@ -24,7 +23,7 @@ readonly class FetchMangaChaptersHandler
throw new MangaNotFoundException(); throw new MangaNotFoundException();
} }
if ($manga->getExternalId() === null) { if($manga->getExternalId() === null){
throw new MangadexApiException("Manga has no external_id"); throw new MangadexApiException("Manga has no external_id");
} }

View File

@@ -13,8 +13,7 @@ readonly class ImportChapterHandler
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private MangaPathManagerInterface $pathManager private MangaPathManagerInterface $pathManager
) { ) {}
}
public function handle(ImportChapter $command): void public function handle(ImportChapter $command): void
{ {

View File

@@ -12,8 +12,7 @@ readonly class ImportVolumeHandler
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private MangaPathManagerInterface $pathManager private MangaPathManagerInterface $pathManager
) { ) {}
}
public function handle(ImportVolume $command): void public function handle(ImportVolume $command): void
{ {

View File

@@ -16,8 +16,7 @@ readonly class RefreshMangaChaptersHandler
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private ChapterSynchronizationServiceInterface $chapterSynchronizationService, private ChapterSynchronizationServiceInterface $chapterSynchronizationService,
private MessageBusInterface $eventBus private MessageBusInterface $eventBus
) { ) {}
}
public function handle(RefreshMangaChapters $command): void public function handle(RefreshMangaChapters $command): void
{ {

View File

@@ -10,8 +10,7 @@ readonly class ToggleMangaMonitoringHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(ToggleMangaMonitoring $command): void public function handle(ToggleMangaMonitoring $command): void
{ {

View File

@@ -12,8 +12,7 @@ readonly class ChapterImportedEventListener
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
) { ) {}
}
public function __invoke(ChapterImported $event): void public function __invoke(ChapterImported $event): void
{ {

View File

@@ -11,8 +11,7 @@ readonly class MangaCreatedEventListener
{ {
public function __construct( public function __construct(
private FetchMangaChaptersHandler $fetchMangaChaptersHandler private FetchMangaChaptersHandler $fetchMangaChaptersHandler
) { ) {}
}
public function __invoke(MangaCreated $event): void public function __invoke(MangaCreated $event): void
{ {

View File

@@ -12,8 +12,7 @@ readonly class VolumeImportedEventListener
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
) { ) {}
}
public function __invoke(VolumeImported $event): void public function __invoke(VolumeImported $event): void
{ {

View File

@@ -8,6 +8,5 @@ readonly class DownloadCbz implements QueryInterface
{ {
public function __construct( public function __construct(
public string $chapterId public string $chapterId
) { ) {}
}
} }

View File

@@ -9,6 +9,5 @@ readonly class DownloadVolume implements QueryInterface
public function __construct( public function __construct(
public string $mangaId, public string $mangaId,
public int $volume public int $volume
) { ) {}
}
} }

View File

@@ -11,3 +11,4 @@ readonly class FindMangaMatchByFilename
) { ) {
} }
} }

View File

@@ -6,6 +6,5 @@ readonly class GetMangaById
{ {
public function __construct( public function __construct(
public string $id public string $id
) { ) {}
}
} }

View File

@@ -6,6 +6,5 @@ readonly class GetMangaBySlug
{ {
public function __construct( public function __construct(
public string $slug public string $slug
) { ) {}
} }
}

View File

@@ -9,6 +9,5 @@ readonly class GetMangaChapters
public ?int $page = 1, public ?int $page = 1,
public ?int $limit = 20, public ?int $limit = 20,
public ?string $sortOrder = 'desc' public ?string $sortOrder = 'desc'
) { ) {}
} }
}

View File

@@ -9,6 +9,5 @@ readonly class GetMangaList
public ?int $limit = 20, public ?int $limit = 20,
public ?string $sortBy = 'title', public ?string $sortBy = 'title',
public ?string $sortOrder = 'asc' public ?string $sortOrder = 'asc'
) { ) {}
} }
}

View File

@@ -9,6 +9,5 @@ readonly class MonitoringCriteria
public function __construct( public function __construct(
public bool $enabled, public bool $enabled,
public ?DateTimeImmutable $lastCheckBefore = null public ?DateTimeImmutable $lastCheckBefore = null
) { ) {}
}
} }

View File

@@ -10,4 +10,4 @@ readonly class SearchLocalManga
public int $limit = 20 public int $limit = 20
) { ) {
} }
} }

View File

@@ -6,6 +6,5 @@ readonly class SearchManga
{ {
public function __construct( public function __construct(
public string $title public string $title
) { ) {}
} }
}

View File

@@ -18,8 +18,7 @@ readonly class DownloadCbzHandler implements QueryHandlerInterface
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private FileServiceInterface $fileService private FileServiceInterface $fileService
) { ) {}
}
public function handle(QueryInterface $query): ResponseInterface public function handle(QueryInterface $query): ResponseInterface
{ {

View File

@@ -17,8 +17,7 @@ readonly class DownloadVolumeHandler implements QueryHandlerInterface
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository, private MangaRepositoryInterface $mangaRepository,
private FileServiceInterface $fileService private FileServiceInterface $fileService
) { ) {}
}
public function handle(QueryInterface $query): ResponseInterface public function handle(QueryInterface $query): ResponseInterface
{ {
@@ -44,8 +43,7 @@ readonly class DownloadVolumeHandler implements QueryHandlerInterface
$cbzPaths[] = $chapter->getPagesDirectory(); $cbzPaths[] = $chapter->getPagesDirectory();
} }
$volumeName = sprintf( $volumeName = sprintf('%s_vol%d',
'%s_vol%d',
$manga->getSlug()->getValue(), $manga->getSlug()->getValue(),
$query->volume $query->volume
); );

View File

@@ -58,7 +58,7 @@ readonly class FindMangaMatchByFilenameHandler
} }
// Trier les résultats par score de correspondance (du plus élevé au plus faible) // Trier les résultats par score de correspondance (du plus élevé au plus faible)
usort($matches, fn ($a, $b) => $b->matchScore <=> $a->matchScore); usort($matches, fn($a, $b) => $b->matchScore <=> $a->matchScore);
return new MangaMatchResponse( return new MangaMatchResponse(
matches: $matches, matches: $matches,
@@ -119,3 +119,4 @@ readonly class FindMangaMatchByFilenameHandler
return $score; return $score;
} }
} }

View File

@@ -11,8 +11,7 @@ readonly class GetMangaByIdHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(GetMangaById $query): MangaResponse public function handle(GetMangaById $query): MangaResponse
{ {

View File

@@ -12,8 +12,7 @@ readonly class GetMangaBySlugHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(GetMangaBySlug $query): MangaResponse public function handle(GetMangaBySlug $query): MangaResponse
{ {

View File

@@ -8,13 +8,11 @@ use App\Domain\Manga\Application\Response\ChapterResponse;
use App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface; use App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface;
use App\Domain\Manga\Domain\Exception\MangaNotFoundException; use App\Domain\Manga\Domain\Exception\MangaNotFoundException;
use App\Domain\Manga\Domain\Model\Chapter; use App\Domain\Manga\Domain\Model\Chapter;
readonly class GetMangaChaptersHandler readonly class GetMangaChaptersHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(GetMangaChapters $query): ChapterListResponse public function handle(GetMangaChapters $query): ChapterListResponse
{ {
@@ -50,4 +48,4 @@ readonly class GetMangaChaptersHandler
limit: $query->limit limit: $query->limit
); );
} }
} }

View File

@@ -10,8 +10,7 @@ readonly class GetMangaListHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $mangaRepository private MangaRepositoryInterface $mangaRepository
) { ) {}
}
public function handle(GetMangaList $query): MangaListResponse public function handle(GetMangaList $query): MangaListResponse
{ {
@@ -31,4 +30,4 @@ readonly class GetMangaListHandler
limit: $query->limit limit: $query->limit
); );
} }
} }

View File

@@ -12,8 +12,7 @@ readonly class SearchLocalMangaHandler
{ {
public function __construct( public function __construct(
private MangaRepositoryInterface $repository private MangaRepositoryInterface $repository
) { ) {}
}
public function handle(SearchLocalManga $query): MangaListResponse public function handle(SearchLocalManga $query): MangaListResponse
{ {

View File

@@ -12,8 +12,7 @@ readonly class SearchMangaHandler
{ {
public function __construct( public function __construct(
private MangaProviderInterface $mangaProvider private MangaProviderInterface $mangaProvider
) { ) {}
}
public function handle(SearchManga $query): MangaSearchResponse public function handle(SearchManga $query): MangaSearchResponse
{ {
@@ -41,4 +40,4 @@ readonly class SearchMangaHandler
) )
); );
} }
} }

View File

@@ -9,8 +9,7 @@ readonly class ChapterListResponse
public int $total, public int $total,
public int $page, public int $page,
public int $limit public int $limit
) { ) {}
}
public function getTotalPages(): int public function getTotalPages(): int
{ {
@@ -26,4 +25,4 @@ readonly class ChapterListResponse
{ {
return $this->page > 1; return $this->page > 1;
} }
} }

View File

@@ -12,6 +12,5 @@ readonly class ChapterResponse
public bool $isVisible, public bool $isVisible,
public ?string $pagesDirectory, public ?string $pagesDirectory,
public string $createdAt public string $createdAt
) { ) {}
}
} }

View File

@@ -9,6 +9,5 @@ readonly class DownloadResponse implements ResponseInterface
{ {
public function __construct( public function __construct(
public Response $httpResponse public Response $httpResponse
) { ) {}
}
} }

View File

@@ -9,8 +9,7 @@ readonly class MangaListResponse
public int $total, public int $total,
public int $page, public int $page,
public int $limit public int $limit
) { ) {}
}
public function getTotalPages(): int public function getTotalPages(): int
{ {
@@ -26,4 +25,4 @@ readonly class MangaListResponse
{ {
return $this->page > 1; return $this->page > 1;
} }
} }

View File

@@ -18,3 +18,4 @@ readonly class MangaMatchItem
) { ) {
} }
} }

View File

@@ -27,3 +27,4 @@ readonly class MangaMatchResponse
return $this->matches[0] ?? null; return $this->matches[0] ?? null;
} }
} }

View File

@@ -19,6 +19,5 @@ readonly class MangaResponse
public ?string $thumbnailUrl, public ?string $thumbnailUrl,
public ?float $rating, public ?float $rating,
public bool $monitored public bool $monitored
) { ) {}
}
} }

View File

@@ -17,6 +17,5 @@ readonly class MangaSearchItem
public ?string $imageUrl, public ?string $imageUrl,
public ?string $thumbnailUrl, public ?string $thumbnailUrl,
public ?float $rating public ?float $rating
) { ) {}
}
} }

View File

@@ -14,4 +14,4 @@ readonly class MangaSearchResponse
{ {
$this->items = $items; $this->items = $items;
} }
} }

View File

@@ -12,8 +12,7 @@ readonly class SearchLocalMangaResponse
public int $total, public int $total,
public int $page, public int $page,
public int $limit public int $limit
) { ) {}
}
public function hasNextPage(): bool public function hasNextPage(): bool
{ {
@@ -24,4 +23,4 @@ readonly class SearchLocalMangaResponse
{ {
return $this->page > 1; return $this->page > 1;
} }
} }

View File

@@ -93,4 +93,4 @@ interface MangadexClientInterface
* } * }
*/ */
public function getManga(string $mangaId): array; public function getManga(string $mangaId): array;
} }

View File

@@ -9,6 +9,6 @@ use App\Domain\Manga\Domain\Model\ValueObject\ExternalId;
interface MangaProviderInterface interface MangaProviderInterface
{ {
public function search(string $title): MangaCollection; public function search(string $title): MangaCollection;
public function findByExternalId(ExternalId $externalId): ?Manga; public function findByExternalId(ExternalId $externalId): ?Manga;
} }

View File

@@ -13,4 +13,4 @@ interface ImageProcessorInterface
* @throws \Exception * @throws \Exception
*/ */
public function createThumbnail(string $originalImagePath): string; public function createThumbnail(string $originalImagePath): string;
} }

View File

@@ -8,6 +8,5 @@ readonly class ChapterReadyForScraping
{ {
public function __construct( public function __construct(
public ChapterId $chapterId public ChapterId $chapterId
) { ) {}
}
} }

View File

@@ -7,6 +7,5 @@ readonly class MangaCreated
public function __construct( public function __construct(
public string $mangaId, public string $mangaId,
public string $externalId public string $externalId
) { ) {}
}
} }

View File

@@ -4,4 +4,4 @@ namespace App\Domain\Manga\Domain\Exception;
class InvalidExternalIdException extends MangaDomainException class InvalidExternalIdException extends MangaDomainException
{ {
} }

View File

@@ -4,4 +4,4 @@ namespace App\Domain\Manga\Domain\Exception;
class InvalidMangaIdException extends MangaDomainException class InvalidMangaIdException extends MangaDomainException
{ {
} }

View File

@@ -4,4 +4,4 @@ namespace App\Domain\Manga\Domain\Exception;
class InvalidMangaSlugException extends MangaDomainException class InvalidMangaSlugException extends MangaDomainException
{ {
} }

View File

@@ -4,4 +4,4 @@ namespace App\Domain\Manga\Domain\Exception;
class InvalidMangaTitleException extends MangaDomainException class InvalidMangaTitleException extends MangaDomainException
{ {
} }

View File

@@ -8,4 +8,4 @@ class MangadexApiException extends MangaDomainException
{ {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
} }
} }

View File

@@ -8,4 +8,4 @@ class MangadexAuthenticationException extends MangaDomainException
{ {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
} }
} }

View File

@@ -42,3 +42,4 @@ readonly class AnalyzedFilename
return $this->volumeNumber !== null; return $this->volumeNumber !== null;
} }
} }

View File

@@ -17,8 +17,7 @@ class Chapter
private ?string $pagesDirectory = null, private ?string $pagesDirectory = null,
private int $pageCount = 0, private int $pageCount = 0,
private \DateTimeImmutable $createdAt = new \DateTimeImmutable() private \DateTimeImmutable $createdAt = new \DateTimeImmutable()
) { ) {}
}
public function getId(): string public function getId(): string
{ {

View File

@@ -24,4 +24,4 @@ readonly class MangaCollection
{ {
return count($this->items); return count($this->items);
} }
} }

View File

@@ -6,8 +6,7 @@ readonly class ChapterId
{ {
public function __construct( public function __construct(
private string $value private string $value
) { ) {}
}
public function getValue(): string public function getValue(): string
{ {

View File

@@ -21,3 +21,4 @@ readonly class ChapterNumber
return $this->value; return $this->value;
} }
} }

View File

@@ -18,4 +18,4 @@ readonly class ExternalId
{ {
return $this->value; return $this->value;
} }
} }

View File

@@ -7,8 +7,7 @@ readonly class ImageUrls
public function __construct( public function __construct(
private string $full, private string $full,
private string $thumbnail private string $thumbnail
) { ) {}
}
public function getFull(): string public function getFull(): string
{ {
@@ -19,4 +18,4 @@ readonly class ImageUrls
{ {
return $this->thumbnail; return $this->thumbnail;
} }
} }

View File

@@ -23,4 +23,4 @@ readonly class MangaId
{ {
return $this->value === $other->value; return $this->value === $other->value;
} }
} }

View File

@@ -22,4 +22,4 @@ readonly class MangaSlug
{ {
return $this->value; return $this->value;
} }
} }

View File

@@ -18,4 +18,4 @@ readonly class MangaTitle
{ {
return $this->value; return $this->value;
} }
} }

View File

@@ -6,8 +6,7 @@ readonly class MonitoringStatus
{ {
public function __construct( public function __construct(
private bool $enabled private bool $enabled
) { ) {}
}
public static function enabled(): self public static function enabled(): self
{ {

View File

@@ -21,3 +21,4 @@ readonly class VolumeNumber
return $this->value; return $this->value;
} }
} }

View File

@@ -18,8 +18,7 @@ final class ImportChapterController extends AbstractController
{ {
public function __construct( public function __construct(
private readonly ImportChapterHandler $commandHandler private readonly ImportChapterHandler $commandHandler
) { ) {}
}
public function __invoke(Request $request): Response public function __invoke(Request $request): Response
{ {
@@ -140,3 +139,7 @@ final class ImportChapterController extends AbstractController
return $errors; return $errors;
} }
} }

View File

@@ -16,8 +16,7 @@ final class ImportVolumeController extends AbstractController
{ {
public function __construct( public function __construct(
private readonly ImportVolumeHandler $commandHandler private readonly ImportVolumeHandler $commandHandler
) { ) {}
}
public function __invoke(Request $request): Response public function __invoke(Request $request): Response
{ {
@@ -133,3 +132,7 @@ final class ImportVolumeController extends AbstractController
return $errors; return $errors;
} }
} }

View File

@@ -12,6 +12,5 @@ readonly class ChapterCollection
public int $limit, public int $limit,
public bool $hasNextPage, public bool $hasNextPage,
public bool $hasPreviousPage public bool $hasPreviousPage
) { ) {}
} }
}

View File

@@ -15,6 +15,5 @@ readonly class ChapterListItem
public bool $isVisible, public bool $isVisible,
public bool $isAvailable, public bool $isAvailable,
public string $createdAt public string $createdAt
) { ) {}
} }
}

View File

@@ -18,3 +18,4 @@ readonly class FilenameMatchCollection
) { ) {
} }
} }

View File

@@ -18,3 +18,4 @@ readonly class FilenameMatchItem
) { ) {
} }
} }

View File

@@ -14,6 +14,5 @@ readonly class MangaCollection
public int $limit, public int $limit,
public bool $hasNextPage, public bool $hasNextPage,
public bool $hasPreviousPage public bool $hasPreviousPage
) { ) {}
} }
}

View File

@@ -22,6 +22,5 @@ readonly class MangaDetail
public ?string $thumbnailUrl, public ?string $thumbnailUrl,
public ?float $rating, public ?float $rating,
public bool $monitored public bool $monitored
) { ) {}
}
} }

View File

@@ -21,6 +21,5 @@ readonly class MangaListItem
public string $status, public string $status,
public ?float $rating, public ?float $rating,
public DateTimeImmutable $createdAt, public DateTimeImmutable $createdAt,
) { ) {}
}
} }

Some files were not shown because too many files have changed in this diff Show More