fix(import): extraire les images CBZ vers le stockage individuel #15
@@ -126,10 +126,10 @@ services:
|
|||||||
tags:
|
tags:
|
||||||
- { name: messenger.message_handler, bus: command.bus }
|
- { name: messenger.message_handler, bus: command.bus }
|
||||||
|
|
||||||
App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface:
|
App\Domain\Shared\Domain\Contract\ImageStorageInterface:
|
||||||
alias: App\Domain\Scraping\Infrastructure\Service\LocalImageStorage
|
alias: App\Domain\Shared\Infrastructure\Service\ImageStorageManager
|
||||||
|
|
||||||
App\Domain\Scraping\Infrastructure\Service\LocalImageStorage:
|
App\Domain\Shared\Infrastructure\Service\ImageStorageManager:
|
||||||
arguments:
|
arguments:
|
||||||
$storagePath: '%kernel.project_dir%/public/images'
|
$storagePath: '%kernel.project_dir%/public/images'
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryScrapingJobRepository'
|
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryScrapingJobRepository'
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface:
|
App\Domain\Shared\Domain\Contract\ImageStorageInterface:
|
||||||
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryImageStorage'
|
class: 'App\Tests\Domain\Scraping\Adapter\InMemoryImageStorage'
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ use App\Domain\Manga\Application\Command\ImportChapter;
|
|||||||
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\Exception\ChapterNotFoundException;
|
use App\Domain\Manga\Domain\Exception\ChapterNotFoundException;
|
||||||
use App\Domain\Shared\Domain\Contract\MangaPathManagerInterface;
|
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
|
||||||
|
|
||||||
readonly class ImportChapterHandler
|
readonly class ImportChapterHandler
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MangaRepositoryInterface $mangaRepository,
|
private MangaRepositoryInterface $mangaRepository,
|
||||||
private MangaPathManagerInterface $pathManager
|
private ImageStorageInterface $imageStorage
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,11 +39,15 @@ readonly class ImportChapterHandler
|
|||||||
throw new ChapterNotFoundException("Chapter {$command->chapterNumber} not found for manga {$command->mangaId}");
|
throw new ChapterNotFoundException("Chapter {$command->chapterNumber} not found for manga {$command->mangaId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Save the CBZ file to storage using the path manager
|
// 4. Extract CBZ into individual images storage
|
||||||
$cbzPath = $this->saveCbzFile($command, $manga, $existingChapter);
|
$pagesDirectory = $this->imageStorage->extractFromCbz(
|
||||||
|
$existingChapter->getId(),
|
||||||
|
$command->fileBinary
|
||||||
|
);
|
||||||
|
$pageCount = $this->imageStorage->countCbzImages($command->fileBinary);
|
||||||
|
|
||||||
// 5. Update existing chapter with new path through the aggregate
|
// 5. Update existing chapter with new path through the aggregate
|
||||||
$manga->updateChapterPages($existingChapter, $cbzPath, $existingChapter->getPageCount());
|
$manga->updateChapterPages($existingChapter, $pagesDirectory, $pageCount);
|
||||||
$this->mangaRepository->save($manga);
|
$this->mangaRepository->save($manga);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,21 +57,4 @@ readonly class ImportChapterHandler
|
|||||||
|
|
||||||
return strpos($fileBinary, $zipMagicNumber) === 0;
|
return strpos($fileBinary, $zipMagicNumber) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function saveCbzFile(ImportChapter $command, \App\Domain\Manga\Domain\Model\Manga $manga, \App\Domain\Manga\Domain\Model\Chapter $chapter): string
|
|
||||||
{
|
|
||||||
$volumeNumber = $chapter->getVolume() ?? 0;
|
|
||||||
$cbzPath = $this->pathManager->buildChapterCbzPath(
|
|
||||||
$manga->getTitle()->getValue(),
|
|
||||||
(string)$manga->getPublicationYear(),
|
|
||||||
$volumeNumber,
|
|
||||||
(string)$command->chapterNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!file_put_contents($cbzPath, $command->fileBinary)) {
|
|
||||||
throw new \RuntimeException('Failed to save CBZ file');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $cbzPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ namespace App\Domain\Manga\Application\CommandHandler;
|
|||||||
use App\Domain\Manga\Application\Command\ImportVolume;
|
use App\Domain\Manga\Application\Command\ImportVolume;
|
||||||
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\Shared\Domain\Contract\MangaPathManagerInterface;
|
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
|
||||||
|
|
||||||
readonly class ImportVolumeHandler
|
readonly class ImportVolumeHandler
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MangaRepositoryInterface $mangaRepository,
|
private MangaRepositoryInterface $mangaRepository,
|
||||||
private MangaPathManagerInterface $pathManager
|
private ImageStorageInterface $imageStorage
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,12 +40,14 @@ readonly class ImportVolumeHandler
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Save the CBZ file to storage using the path manager
|
// 4. Extract CBZ into individual images storage (shared directory for all volume chapters)
|
||||||
$cbzPath = $this->saveCbzFile($command, $manga);
|
$volumeDirectoryId = sprintf('volume_%s_%d', $command->mangaId, $command->volumeNumber);
|
||||||
|
$pagesDirectory = $this->imageStorage->extractFromCbz($volumeDirectoryId, $command->fileBinary);
|
||||||
|
$pageCount = $this->imageStorage->countCbzImages($command->fileBinary);
|
||||||
|
|
||||||
// 5. Update all chapters with the volume path through the aggregate
|
// 5. Update all chapters with the volume path through the aggregate
|
||||||
foreach ($chapters as $chapter) {
|
foreach ($chapters as $chapter) {
|
||||||
$manga->updateChapterPages($chapter, $cbzPath, $chapter->getPageCount());
|
$manga->updateChapterPages($chapter, $pagesDirectory, $pageCount);
|
||||||
}
|
}
|
||||||
$this->mangaRepository->save($manga);
|
$this->mangaRepository->save($manga);
|
||||||
}
|
}
|
||||||
@@ -56,19 +58,4 @@ readonly class ImportVolumeHandler
|
|||||||
|
|
||||||
return strpos($fileBinary, $zipMagicNumber) === 0;
|
return strpos($fileBinary, $zipMagicNumber) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function saveCbzFile(ImportVolume $command, \App\Domain\Manga\Domain\Model\Manga $manga): string
|
|
||||||
{
|
|
||||||
$cbzPath = $this->pathManager->buildVolumeCbzPath(
|
|
||||||
$manga->getTitle()->getValue(),
|
|
||||||
(string)$manga->getPublicationYear(),
|
|
||||||
$command->volumeNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!file_put_contents($cbzPath, $command->fileBinary)) {
|
|
||||||
throw new \RuntimeException('Failed to save CBZ file');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $cbzPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ readonly class LegacyChapterRepository implements ChapterRepositoryInterface
|
|||||||
$pages[] = new Page(
|
$pages[] = new Page(
|
||||||
basename($files[$i]),
|
basename($files[$i]),
|
||||||
new PageNumber($i + 1),
|
new PageNumber($i + 1),
|
||||||
sprintf('/images/pages/%s/%s', $chapterId->getValue(), basename($files[$i])),
|
sprintf('/images/pages/%s/%s', basename($pagesDirectory), basename($files[$i])),
|
||||||
$imageSize[0],
|
$imageSize[0],
|
||||||
$imageSize[1]
|
$imageSize[1]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use App\Domain\Scraping\Application\Command\ScrapeChapter;
|
|||||||
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
|
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
|
||||||
use App\Domain\Scraping\Domain\Contract\Repository\MangaRepositoryInterface;
|
use App\Domain\Scraping\Domain\Contract\Repository\MangaRepositoryInterface;
|
||||||
use App\Domain\Scraping\Domain\Contract\Repository\SourceRepositoryInterface;
|
use App\Domain\Scraping\Domain\Contract\Repository\SourceRepositoryInterface;
|
||||||
use App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface;
|
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
|
||||||
use App\Domain\Scraping\Domain\Contract\Service\ImageDownloaderInterface;
|
use App\Domain\Scraping\Domain\Contract\Service\ImageDownloaderInterface;
|
||||||
use App\Domain\Scraping\Domain\Contract\Service\ScraperFactoryInterface;
|
use App\Domain\Scraping\Domain\Contract\Service\ScraperFactoryInterface;
|
||||||
use App\Domain\Shared\Domain\Event\ChapterScraped;
|
use App\Domain\Shared\Domain\Event\ChapterScraped;
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Domain\Scraping\Domain\Contract\Service;
|
|
||||||
|
|
||||||
interface ImageStorageInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Copies images to permanent storage. Returns the pagesDirectory path.
|
|
||||||
*
|
|
||||||
* @param string $chapterId The chapter UUID used as directory name
|
|
||||||
* @param string[] $localImagePaths Paths to the locally downloaded image files
|
|
||||||
*
|
|
||||||
* @return string Absolute path to the directory where images were stored
|
|
||||||
*/
|
|
||||||
public function storeChapterImages(string $chapterId, array $localImagePaths): string;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Domain\Scraping\Infrastructure\Service;
|
|
||||||
|
|
||||||
use App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface;
|
|
||||||
|
|
||||||
readonly class LocalImageStorage implements ImageStorageInterface
|
|
||||||
{
|
|
||||||
public function __construct(private string $storagePath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function storeChapterImages(string $chapterId, array $localImagePaths): string
|
|
||||||
{
|
|
||||||
$targetDir = $this->storagePath . '/pages/' . $chapterId;
|
|
||||||
|
|
||||||
if (!is_dir($targetDir)) {
|
|
||||||
mkdir($targetDir, 0755, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
sort($localImagePaths);
|
|
||||||
|
|
||||||
foreach ($localImagePaths as $index => $localPath) {
|
|
||||||
$extension = pathinfo($localPath, PATHINFO_EXTENSION) ?: 'jpg';
|
|
||||||
$targetFile = sprintf('%s/%03d.%s', $targetDir, $index + 1, $extension);
|
|
||||||
copy($localPath, $targetFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $targetDir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
src/Domain/Shared/Domain/Contract/ImageStorageInterface.php
Normal file
28
src/Domain/Shared/Domain/Contract/ImageStorageInterface.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Shared\Domain\Contract;
|
||||||
|
|
||||||
|
interface ImageStorageInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Store images from local file paths into the individual images storage.
|
||||||
|
* Used by the scraping flow.
|
||||||
|
*
|
||||||
|
* @param string[] $localImagePaths
|
||||||
|
* @return string The directory path where images are stored (pagesDirectory)
|
||||||
|
*/
|
||||||
|
public function storeChapterImages(string $targetId, array $localImagePaths): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract images from a CBZ binary into the individual images storage.
|
||||||
|
* Used by the import flow.
|
||||||
|
*
|
||||||
|
* @return string The directory path where images are stored (pagesDirectory)
|
||||||
|
*/
|
||||||
|
public function extractFromCbz(string $targetId, string $cbzBinary): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count images in a CBZ binary.
|
||||||
|
*/
|
||||||
|
public function countCbzImages(string $cbzBinary): int;
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Shared\Infrastructure\Service;
|
||||||
|
|
||||||
|
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
|
||||||
|
use ZipArchive;
|
||||||
|
|
||||||
|
class ImageStorageManager implements ImageStorageInterface
|
||||||
|
{
|
||||||
|
public function __construct(private string $storagePath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storeChapterImages(string $targetId, array $localImagePaths): string
|
||||||
|
{
|
||||||
|
$targetDir = $this->storagePath . '/pages/' . $targetId;
|
||||||
|
|
||||||
|
if (!is_dir($targetDir)) {
|
||||||
|
mkdir($targetDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
sort($localImagePaths);
|
||||||
|
|
||||||
|
foreach ($localImagePaths as $index => $localPath) {
|
||||||
|
$extension = pathinfo($localPath, PATHINFO_EXTENSION) ?: 'jpg';
|
||||||
|
$targetFile = sprintf('%s/%03d.%s', $targetDir, $index + 1, $extension);
|
||||||
|
copy($localPath, $targetFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $targetDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extractFromCbz(string $targetId, string $cbzBinary): string
|
||||||
|
{
|
||||||
|
$targetDir = $this->storagePath . '/pages/' . $targetId;
|
||||||
|
|
||||||
|
if (!is_dir($targetDir)) {
|
||||||
|
mkdir($targetDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpFile = tempnam(sys_get_temp_dir(), 'cbz_');
|
||||||
|
file_put_contents($tmpFile, $cbzBinary);
|
||||||
|
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
if ($zip->open($tmpFile) !== true) {
|
||||||
|
unlink($tmpFile);
|
||||||
|
throw new \RuntimeException('Failed to open CBZ file as ZIP archive');
|
||||||
|
}
|
||||||
|
|
||||||
|
$imageEntries = [];
|
||||||
|
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||||
|
$name = $zip->getNameIndex($i);
|
||||||
|
if (preg_match('/\.(jpg|jpeg|png|webp|gif)$/i', $name)) {
|
||||||
|
$imageEntries[] = ['index' => $i, 'name' => $name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usort($imageEntries, fn ($a, $b) => strcmp($a['name'], $b['name']));
|
||||||
|
|
||||||
|
foreach ($imageEntries as $seq => $entry) {
|
||||||
|
$extension = strtolower(pathinfo($entry['name'], PATHINFO_EXTENSION)) ?: 'jpg';
|
||||||
|
$targetFile = sprintf('%s/%03d.%s', $targetDir, $seq + 1, $extension);
|
||||||
|
$content = $zip->getFromIndex($entry['index']);
|
||||||
|
file_put_contents($targetFile, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
unlink($tmpFile);
|
||||||
|
|
||||||
|
return $targetDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countCbzImages(string $cbzBinary): int
|
||||||
|
{
|
||||||
|
$tmpFile = tempnam(sys_get_temp_dir(), 'cbz_');
|
||||||
|
file_put_contents($tmpFile, $cbzBinary);
|
||||||
|
|
||||||
|
$zip = new ZipArchive();
|
||||||
|
if ($zip->open($tmpFile) !== true) {
|
||||||
|
unlink($tmpFile);
|
||||||
|
throw new \RuntimeException('Failed to open CBZ file as ZIP archive');
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||||
|
$name = $zip->getNameIndex($i);
|
||||||
|
if (preg_match('/\.(jpg|jpeg|png|webp|gif)$/i', $name)) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
unlink($tmpFile);
|
||||||
|
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,22 +13,22 @@ use App\Domain\Manga\Domain\Model\ValueObject\MangaId;
|
|||||||
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
|
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
|
||||||
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
|
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
|
||||||
use App\Tests\Domain\Manga\Adapter\InMemoryMangaRepository;
|
use App\Tests\Domain\Manga\Adapter\InMemoryMangaRepository;
|
||||||
use App\Tests\Domain\Manga\Adapter\InMemoryPathManager;
|
use App\Tests\Domain\Scraping\Adapter\InMemoryImageStorage;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class ImportChapterHandlerTest extends TestCase
|
class ImportChapterHandlerTest extends TestCase
|
||||||
{
|
{
|
||||||
private InMemoryMangaRepository $mangaRepository;
|
private InMemoryMangaRepository $mangaRepository;
|
||||||
private InMemoryPathManager $pathManager;
|
private InMemoryImageStorage $imageStorage;
|
||||||
private ImportChapterHandler $handler;
|
private ImportChapterHandler $handler;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->mangaRepository = new InMemoryMangaRepository();
|
$this->mangaRepository = new InMemoryMangaRepository();
|
||||||
$this->pathManager = new InMemoryPathManager();
|
$this->imageStorage = new InMemoryImageStorage();
|
||||||
$this->handler = new ImportChapterHandler(
|
$this->handler = new ImportChapterHandler(
|
||||||
$this->mangaRepository,
|
$this->mangaRepository,
|
||||||
$this->pathManager
|
$this->imageStorage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,22 @@ use App\Domain\Manga\Domain\Model\ValueObject\MangaId;
|
|||||||
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
|
use App\Domain\Manga\Domain\Model\ValueObject\MangaSlug;
|
||||||
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
|
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
|
||||||
use App\Tests\Domain\Manga\Adapter\InMemoryMangaRepository;
|
use App\Tests\Domain\Manga\Adapter\InMemoryMangaRepository;
|
||||||
use App\Tests\Domain\Manga\Adapter\InMemoryPathManager;
|
use App\Tests\Domain\Scraping\Adapter\InMemoryImageStorage;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class ImportVolumeHandlerTest extends TestCase
|
class ImportVolumeHandlerTest extends TestCase
|
||||||
{
|
{
|
||||||
private InMemoryMangaRepository $mangaRepository;
|
private InMemoryMangaRepository $mangaRepository;
|
||||||
private InMemoryPathManager $pathManager;
|
private InMemoryImageStorage $imageStorage;
|
||||||
private ImportVolumeHandler $handler;
|
private ImportVolumeHandler $handler;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->mangaRepository = new InMemoryMangaRepository();
|
$this->mangaRepository = new InMemoryMangaRepository();
|
||||||
$this->pathManager = new InMemoryPathManager();
|
$this->imageStorage = new InMemoryImageStorage();
|
||||||
$this->handler = new ImportVolumeHandler(
|
$this->handler = new ImportVolumeHandler(
|
||||||
$this->mangaRepository,
|
$this->mangaRepository,
|
||||||
$this->pathManager
|
$this->imageStorage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,31 @@
|
|||||||
|
|
||||||
namespace App\Tests\Domain\Scraping\Adapter;
|
namespace App\Tests\Domain\Scraping\Adapter;
|
||||||
|
|
||||||
use App\Domain\Scraping\Domain\Contract\Service\ImageStorageInterface;
|
use App\Domain\Shared\Domain\Contract\ImageStorageInterface;
|
||||||
|
|
||||||
class InMemoryImageStorage implements ImageStorageInterface
|
class InMemoryImageStorage implements ImageStorageInterface
|
||||||
{
|
{
|
||||||
/** @var array<string, string> chapterId => pagesDirectory */
|
/** @var array<string, string> targetId => pagesDirectory */
|
||||||
public array $stored = [];
|
public array $stored = [];
|
||||||
|
|
||||||
public function storeChapterImages(string $chapterId, array $localImagePaths): string
|
public function storeChapterImages(string $targetId, array $localImagePaths): string
|
||||||
{
|
{
|
||||||
$dir = '/fake/pages/' . $chapterId;
|
$dir = '/fake/pages/' . $targetId;
|
||||||
$this->stored[$chapterId] = $dir;
|
$this->stored[$targetId] = $dir;
|
||||||
|
|
||||||
return $dir;
|
return $dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function extractFromCbz(string $targetId, string $cbzBinary): string
|
||||||
|
{
|
||||||
|
$dir = '/fake/pages/' . $targetId;
|
||||||
|
$this->stored[$targetId] = $dir;
|
||||||
|
|
||||||
|
return $dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countCbzImages(string $cbzBinary): int
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user