107 lines
4.1 KiB
PHP
107 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\Manga\Infrastructure\Service;
|
|
|
|
use App\Domain\Manga\Domain\Contract\Service\FilenameAnalyzerInterface;
|
|
use App\Domain\Manga\Domain\Model\AnalyzedFilename;
|
|
use App\Domain\Manga\Domain\Model\ValueObject\ChapterNumber;
|
|
use App\Domain\Manga\Domain\Model\ValueObject\MangaTitle;
|
|
use App\Domain\Manga\Domain\Model\ValueObject\VolumeNumber;
|
|
|
|
readonly class FilenameAnalyzer implements FilenameAnalyzerInterface
|
|
{
|
|
public function analyze(string $filename): AnalyzedFilename
|
|
{
|
|
// Enlever l'extension
|
|
$nameWithoutExtension = preg_replace('/\.(cbz|cbr)$/i', '', $filename);
|
|
|
|
// Extraire les informations en utilisant la logique du CbzService
|
|
$titleStr = $this->extractTitle($nameWithoutExtension);
|
|
$volumeNumber = $this->extractVolume($nameWithoutExtension);
|
|
$chapterNumber = $this->extractChapter($nameWithoutExtension);
|
|
|
|
$cleanedTitle = $this->cleanTitle($titleStr);
|
|
|
|
return new AnalyzedFilename(
|
|
title: new MangaTitle($cleanedTitle),
|
|
chapterNumber: $chapterNumber !== null ? new ChapterNumber($chapterNumber) : null,
|
|
volumeNumber: $volumeNumber !== null ? new VolumeNumber((float) $volumeNumber) : null
|
|
);
|
|
}
|
|
|
|
private function extractTitle(string $fileName): string
|
|
{
|
|
// Pattern principal : titre suivi de volume/chapitre (inspiré du CbzService)
|
|
// Supporte: vol, volume, tome, t, ch, chap, chapter, chapitre
|
|
$titlePattern = '/^(?P<title>.+?)(?:\s*-\s*|\s+)?(?:(?:[Tt]ome|[Vv]ol(?:ume)?\.?|[Cc]h(?:ap(?:itre|ter)?)?|[Tt])\s*\d+)/';
|
|
if (preg_match($titlePattern, $fileName, $matches)) {
|
|
return trim($matches['title']);
|
|
}
|
|
|
|
// Pattern underscore : titre_vol123 ou titre_ch456 ou titre_chapter_1094
|
|
$underscorePattern = '/^(?P<title>.*?)_(?:vol|tome|t|ch|chap|chapter|chapitre)[\s_-]*\d+/i';
|
|
if (preg_match($underscorePattern, $fileName, $matches)) {
|
|
return trim($matches['title']);
|
|
}
|
|
|
|
// Pattern avec tiret : titre-vol123 ou titre-ch456 ou titre-tome-50
|
|
$dashPattern = '/^(?P<title>.*?)-(?:vol|tome|t|ch|chap|chapter|chapitre)[\s_-]*\d+/i';
|
|
if (preg_match($dashPattern, $fileName, $matches)) {
|
|
return trim($matches['title']);
|
|
}
|
|
|
|
// Pattern underscore simple : titre_123
|
|
$newFormatPattern = '/^(?P<title>.*?)_\d+/';
|
|
if (preg_match($newFormatPattern, $fileName, $matches)) {
|
|
return trim($matches['title']);
|
|
}
|
|
|
|
// Si aucun pattern ne matche, retourner le nom sans extension
|
|
return $fileName;
|
|
}
|
|
|
|
private function extractVolume(string $fileName): ?int
|
|
{
|
|
// Pattern pour volume : vol123, volume123, tome123, t123, v123
|
|
$volumePattern = '/(?:[Tt]ome|[Vv]ol(?:ume)?\.?|[Tt]|[Vv])[\s\-_]*(?P<volume>\d+)/i';
|
|
if (preg_match($volumePattern, $fileName, $matches)) {
|
|
return (int) $matches['volume'];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function extractChapter(string $fileName): ?float
|
|
{
|
|
// Pattern pour chapitre : ch123, chap123, chapter123, chapitre123
|
|
$chapterPattern = '/[Cc]h(?:ap(?:itre|ter)?)?[\s\-_]*(?P<chapter>\d+(?:\.\d+)?)/i';
|
|
if (preg_match($chapterPattern, $fileName, $matches)) {
|
|
return (float) $matches['chapter'];
|
|
}
|
|
|
|
// Pattern underscore à la fin : _123.cbz
|
|
$newFormatPattern = '/_ch(?P<chapter>\d+(?:\.\d+)?)(?:\.\w+)?$/i';
|
|
if (preg_match($newFormatPattern, $fileName, $matches)) {
|
|
return (float) $matches['chapter'];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function cleanTitle(string $title): string
|
|
{
|
|
// Enlever les patterns communs (avec séparateurs possibles)
|
|
$cleanTitle = preg_replace('/[\s\-_]?(?:scan|raw|fr|en|jp|hq|lq)[\s\-_]?/i', ' ', $title);
|
|
|
|
// Enlever les caractères spéciaux en début/fin
|
|
$cleanTitle = trim($cleanTitle, ' -_.');
|
|
|
|
// Normaliser les espaces multiples
|
|
$cleanTitle = preg_replace('/\s+/', ' ', $cleanTitle);
|
|
|
|
return trim($cleanTitle);
|
|
}
|
|
}
|