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
.+?)(?:\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.*?)_(?: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.*?)-(?: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.*?)_\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\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\d+(?:\.\d+)?)/i';
if (preg_match($chapterPattern, $fileName, $matches)) {
return (float) $matches['chapter'];
}
// Pattern underscore à la fin : _123.cbz
$newFormatPattern = '/_ch(?P\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);
}
}