open($chemin) !== true) { throw new RuntimeException(t('Le fichier est illisible ou endommagé.')); } $texte = ''; // Parcours dans l'ordre des motifs : l'en-tête sort avant le corps, quel que soit l'ordre dans l'archive foreach ($parties as $motif) { for ($i = 0; $i < $zip->numFiles; $i++) { $nom = (string) $zip->getNameIndex($i); if (preg_match($motif, $nom)) { $xml = (string) $zip->getFromIndex($i); $xml = preg_replace('#<(w:tab|text:tab)\b[^>]*/>#', "\t", $xml) ?? $xml; $xml = preg_replace('#<(w:br|w:cr|text:line-break)\b[^>]*/>#', "\n", $xml) ?? $xml; $xml = preg_replace('##', "\n", $xml) ?? $xml; $texte .= html_entity_decode(strip_tags($xml), ENT_QUOTES | ENT_XML1, 'UTF-8') . "\n"; } } } $zip->close(); return $texte; }; $texte = match ($extension) { 'pdf' => null, 'md', 'txt' => (string) file_get_contents($chemin), // L'en-tête et le pied de page portent souvent les coordonnées 'docx' => $lireXml($chemin, ['#^word/header\d*\.xml$#', '#^word/document\.xml$#', '#^word/footer\d*\.xml$#'], ['w:p']), 'odt' => $lireXml($chemin, ['#^content\.xml$#'], ['text:p', 'text:h']), default => throw new RuntimeException(t('L\'analyse automatique lit les fichiers PDF, DOCX, ODT, MD et TXT. Convertissez ce fichier en PDF.')), }; if ($texte === null) { return null; } if (!mb_check_encoding($texte, 'UTF-8')) { $texte = mb_convert_encoding($texte, 'UTF-8', 'Windows-1252'); } $texte = trim(preg_replace("/\n{3,}/", "\n\n", preg_replace('/[ \t]+\n/', "\n", $texte) ?? $texte) ?? $texte); if (mb_strlen($texte) < 200) { throw new RuntimeException(t('Le fichier contient trop peu de texte. S\'il s\'agit d\'un document scanné, chargez-le en PDF.')); } return mb_substr($texte, 0, 150000); }