Added:
- CbrToCbzConverter.php - import now convert .cbr to .cbz - import improvement, multiple files
This commit is contained in:
67
src/Service/CbrToCbzConverter.php
Normal file
67
src/Service/CbrToCbzConverter.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class CbrToCbzConverter
|
||||
{
|
||||
private string $tempDir;
|
||||
private Filesystem $filesystem;
|
||||
|
||||
public function __construct(string $projectDir)
|
||||
{
|
||||
$this->tempDir = $projectDir . '/public/tmp';
|
||||
$this->filesystem = new Filesystem();
|
||||
}
|
||||
|
||||
public function convert(string $cbrPath): string
|
||||
{
|
||||
$tempDir = $this->tempDir . '/' . uniqid('cbr_conversion_');
|
||||
$this->filesystem->mkdir($tempDir);
|
||||
|
||||
$extractDir = $tempDir . '/extract';
|
||||
$this->filesystem->mkdir($extractDir);
|
||||
|
||||
$process = new Process(['unrar-free', 'x', $cbrPath, $extractDir]);
|
||||
$process->run();
|
||||
|
||||
// Si unrar échoue, essayer avec 7z
|
||||
if (!$process->isSuccessful()) {
|
||||
$process = new Process(['7z', 'x', $cbrPath, "-o$extractDir"]);
|
||||
$process->run();
|
||||
|
||||
if (!$process->isSuccessful()) {
|
||||
throw new \RuntimeException("Extraction failed: " . $process->getErrorOutput());
|
||||
}
|
||||
}
|
||||
|
||||
// Créer le CBZ
|
||||
$cbzFileName = pathinfo($cbrPath, PATHINFO_FILENAME) . '.cbz';
|
||||
$cbzPath = $this->tempDir . '/' . $cbzFileName;
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($cbzPath, \ZipArchive::CREATE) !== TRUE) {
|
||||
throw new \RuntimeException("Cannot create ZIP file");
|
||||
}
|
||||
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($extractDir),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen($extractDir) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
$this->filesystem->remove($tempDir);
|
||||
|
||||
return $cbzPath;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,13 @@ class CbzService
|
||||
if (preg_match($titlePattern, $fileName, $matches)) {
|
||||
return $this->slugger->slug(trim($matches['title']), '-')->lower()->toString();
|
||||
}
|
||||
return '';
|
||||
|
||||
$newFormatPattern = '/^(?P<title>.*?)_\d+/';
|
||||
if (preg_match($newFormatPattern, $fileName, $matches)) {
|
||||
return $this->slugger->slug(trim($matches['title']), '-')->lower()->toString();
|
||||
}
|
||||
|
||||
return $this->slugger->slug(pathinfo($fileName, PATHINFO_FILENAME), '-')->lower()->toString();
|
||||
}
|
||||
|
||||
private function extractVolume(string $fileName): string
|
||||
@@ -121,6 +127,12 @@ class CbzService
|
||||
if (preg_match($chapterPattern, $fileName, $matches)) {
|
||||
return $matches['chapter'];
|
||||
}
|
||||
|
||||
$newFormatPattern = '/_(?P<chapter>\d+)(?:\.\w+)?$/';
|
||||
if (preg_match($newFormatPattern, $fileName, $matches)) {
|
||||
return $matches['chapter'];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\Chapter;
|
||||
use App\Entity\Manga;
|
||||
use App\Repository\ChapterRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -18,7 +19,6 @@ class MangaImportService
|
||||
private readonly string $projectDir,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly ChapterRepository $chapterRepository,
|
||||
private readonly CbzService $cbzService,
|
||||
private readonly Filesystem $filesystem,
|
||||
private readonly SluggerInterface $slugger
|
||||
)
|
||||
@@ -28,42 +28,65 @@ class MangaImportService
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
#[NoReturn] public function importVolume(Manga $manga, int $volume, string $tempFilePath, string $originalFileName): void
|
||||
public function importFile(Manga $manga, ?int $volume, ?Chapter $chapter, string $tempFilePath): void
|
||||
{
|
||||
// Extraire les métadonnées du fichier CBZ
|
||||
$metadata = $this->cbzService->extractMetadata($tempFilePath, $originalFileName);
|
||||
if ($chapter !== null) {
|
||||
$this->importChapter($manga, $chapter, $tempFilePath);
|
||||
} elseif ($volume !== null) {
|
||||
$this->importVolume($manga, $volume, $tempFilePath);
|
||||
} else {
|
||||
throw new \RuntimeException("Impossible de déterminer s'il s'agit d'un volume ou d'un chapitre.");
|
||||
}
|
||||
}
|
||||
|
||||
// Créer le nom de fichier et le chemin pour le stockage permanent
|
||||
$permanentFileName = $this->createPermanentFileName($manga, $volume, $metadata);
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function importVolume(Manga $manga, int $volume, string $tempFilePath): void
|
||||
{
|
||||
$permanentFileName = $this->createPermanentFileName($manga, $volume);
|
||||
$mangaDirectory = $this->createMangaDirectory($manga);
|
||||
$permanentFilePath = $this->projectDir . '/' . $mangaDirectory .'/volume_' . sprintf('%02d', $volume) . '/' . $permanentFileName;
|
||||
|
||||
// Vérifier si le fichier existe déjà
|
||||
if ($this->filesystem->exists($permanentFilePath)) {
|
||||
throw new \RuntimeException("Un fichier pour ce volume/chapitre existe déjà.");
|
||||
throw new \RuntimeException("Un fichier pour ce volume existe déjà.");
|
||||
}
|
||||
|
||||
// Déplacer le fichier vers l'emplacement permanent
|
||||
$this->filesystem->mkdir(dirname($permanentFilePath), 0755);
|
||||
$this->filesystem->rename($tempFilePath, $permanentFilePath, true);
|
||||
|
||||
// Mettre à jour ou créer les entités Chapter
|
||||
if (isset($metadata['chapter'])) {
|
||||
// Si c'est un chapitre spécifique
|
||||
$this->updateChapter($manga, $volume, $metadata['chapter'], $permanentFilePath);
|
||||
} else {
|
||||
// Si c'est un volume entier, mettre à jour tous les chapitres du volume
|
||||
$this->updateVolumeChapters($manga, $volume, $permanentFilePath);
|
||||
}
|
||||
$this->updateVolumeChapters($manga, $volume, $permanentFilePath);
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
private function createPermanentFileName(Manga $manga, int $volume, array $metadata): string
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function importChapter(Manga $manga, Chapter $chapter, string $tempFilePath): void
|
||||
{
|
||||
$volume = $chapter->getVolume();
|
||||
$permanentFileName = $this->createPermanentFileName($manga, $volume, $chapter->getNumber());
|
||||
$mangaDirectory = $this->createMangaDirectory($manga);
|
||||
$permanentFilePath = $this->projectDir . '/' . $mangaDirectory .'/volume_' . sprintf('%02d', $volume) . '/' . $permanentFileName;
|
||||
|
||||
if ($this->filesystem->exists($permanentFilePath)) {
|
||||
throw new \RuntimeException("Un fichier pour ce chapitre existe déjà.");
|
||||
}
|
||||
|
||||
$this->filesystem->mkdir(dirname($permanentFilePath), 0755);
|
||||
$this->filesystem->rename($tempFilePath, $permanentFilePath, true);
|
||||
|
||||
$chapter->setCbzPath($permanentFilePath);
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
private function createPermanentFileName(Manga $manga, int $volume, ?float $chapterNumber = null): string
|
||||
{
|
||||
$baseFileName = $this->slugger->slug($manga->getTitle()) . '_vol' . sprintf('%02d', $volume);
|
||||
if (isset($metadata['chapter'])) {
|
||||
$baseFileName .= '_ch' . $metadata['chapter'];
|
||||
if ($chapterNumber !== null) {
|
||||
$baseFileName .= '_ch' . $chapterNumber;
|
||||
}
|
||||
return $baseFileName . '.cbz';
|
||||
}
|
||||
@@ -77,21 +100,6 @@ class MangaImportService
|
||||
return $directoryPath;
|
||||
}
|
||||
|
||||
private function updateChapter(Manga $manga, int $volume, float $chapterNumber, string $cbzPath): void
|
||||
{
|
||||
$chapter = $this->chapterRepository->findOneBy([
|
||||
'manga' => $manga,
|
||||
'volume' => $volume,
|
||||
'number' => $chapterNumber
|
||||
]);
|
||||
|
||||
if (!$chapter) {
|
||||
throw new \RuntimeException("Le chapitre $chapterNumber du volume $volume n'existe pas en base de données.");
|
||||
}
|
||||
|
||||
$chapter->setCbzPath($cbzPath);
|
||||
}
|
||||
|
||||
private function updateVolumeChapters(Manga $manga, int $volume, string $cbzPath): void
|
||||
{
|
||||
$chapters = $this->chapterRepository->findBy([
|
||||
|
||||
Reference in New Issue
Block a user