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<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); } }