Corrige l'import de chapitres/volumes CBZ qui stockait le chemin du fichier CBZ comme pagesDirectory. Le reader ne trouvait aucune image car LegacyChapterRepository attend un dossier d'images individuelles. - Déplace ImageStorageInterface dans Shared (storeChapterImages + extractFromCbz + countCbzImages) - Crée ImageStorageManager dans Shared/Infrastructure (extraction ZIP + copie) - Supprime LocalImageStorage et l'ancienne interface dans Scraping - Refactore ImportChapterHandler et ImportVolumeHandler pour utiliser ImageStorageInterface - Corrige LegacyChapterRepository : construit l'URL depuis basename(pagesDirectory) au lieu de chapterId (fix pour les volumes partagés)
98 lines
2.8 KiB
PHP
98 lines
2.8 KiB
PHP
<?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;
|
|
}
|
|
}
|