cii-text-analysis/Lib/Utils/StringCleaner.php

175 lines
5 KiB
PHP
Raw Permalink Normal View History

2026-02-10 16:19:59 +01:00
<?php
declare(strict_types=1);
namespace Classifier\Lib\Utils;
class StringCleaner
{
/** @var string[] */
private $stopWords;
public function __construct(array $stopWords = [])
{
$this->stopWords = array_map(function (string $word) {
return trim(mb_strtolower($word, 'UTF-8'));
}, $stopWords);
}
public function getCleanChain(string $text): string
{
$text = $this->toUtf8($text);
$text = $this->handleAcronyms($text);
$text = mb_strtolower($text, 'UTF-8');
$text = $this->translitterate($text);
return $this->removeMultiSpaces($text); // "alerte mise en securite"
}
/**
* Nettoie une chaîne de caractères en appliquant plusieurs étapes de transformation
*
* @param string $text
* @return string[] Tableau de mots nettoyés
*/
public function preprocessMessage(string $text): array
{
$text = $this->toUtf8($text);
$text = mb_strtolower($text, 'UTF-8');
$text = $this->handleAcronyms($text);
$text = $this->fromUtf8ToPlainText($text);
$text = $this->safelyRemoveEmptyLines($text);
$text = $this->controlCharToSpace($text);
$text = $this->translitterate($text);
$text = $this->removeMultiSpaces($text);
$words = $this->cutIntoWords($text);
$filteredWords = $this->removeStopWords($words);
return array_values($filteredWords);
}
private function cutIntoWords(string $text): array
{
return explode(' ', $text);
}
private function handleAcronyms(string $text): string
{
// Transforme "P O I" ou "P.O.I" en "POI"
return preg_replace('/(?<=\b\w)\s(?=\w\b)/', '', $text);
}
/**
* Translittération (enlève les accents proprement)
*/
private function translitterate(string $value): string
{
// *Translittération (enlève les accents proprement)
$transliterated = false;
if (class_exists('\Transliterator')) {
$transliterator = \Transliterator::create('Any-Latin; Latin-ASCII');
if ($transliterator) {
$result = $transliterator->transliterate($value);
if ($result !== false) {
$value = $result;
$transliterated = true;
}
}
}
if (!$transliterated && function_exists('iconv')) {
$result = iconv('UTF-8', 'ASCII//TRANSLIT', $value);
if ($result !== false) {
$value = $result;
}
}
return preg_replace('/[^\p{L}\p{N}\s]/u', '', $value);
}
/**
* Remplace les caractères de contrôle (sauf les espaces) par des espaces
*/
private function controlCharToSpace(string $value): string
{
return preg_replace('/[\x00-\x1F\x7F]+/', ' ', $value);
}
private function removeMultiSpaces(string $value): string
{
return trim(preg_replace('/\s+/', ' ', $value));
}
/**
* Supprime les stop words d'un tableau de mots
* et les mots de 1 caractère ou moins
*
* @param string[] $words
*/
private function removeStopWords(array $words): array
{
return array_filter($words, function ($word) {
return !in_array($word, $this->stopWords) && mb_strlen($word) > 1;
});
}
/**
* Convertit une chaîne UTF-8 en texte brut, en supprimant les balises et en décodant les entités HTML
*/
private function fromUtf8ToPlainText(string $value): string
{
// * Supprimer les balises
$output = strip_tags($value);
// * Convertir les entités html (ex: &amp; devient &)
$output = html_entity_decode($output, ENT_QUOTES | ENT_HTML5, 'UTF-8');
return $output;
}
/**
* Supprime les lignes vides ou ne contenant que des espaces/tabs, et normalise les sauts de ligne
*/
private function safelyRemoveEmptyLines(string $value): string
{
// * Remplace les lignes ne contenant que des espaces/tabs par une chaîne vide
$result = preg_replace('/^\s*[\r\n]+/m', '', $value);
// * Remplace les sauts de lignes avec un `\n` unique
$result = preg_replace('/\R/', "\n", $result);
return $result ?? $value;
}
/**
* Convertit intelligemment vers UTF-8
*
* @param mixed $value
* @return string
*/
private function toUtf8($value): string
{
if ($value === null || $value === '') {
return '';
}
$str = (string)$value;
if (mb_check_encoding($str, 'UTF-8')) {
return $str;
}
// * Détection du symbole € en ISO-8859-15 (\xA4)
if (strpos($str, "\xA4") !== false) {
$converted = iconv('ISO-8859-15', 'UTF-8//IGNORE', $str);
return ($converted !== false) ? $converted : $str;
}
// * Tenter conversion de ISO-8859-1 vers UTF-8
$converted = iconv('ISO-8859-1', 'UTF-8//IGNORE', $str);
return ($converted !== false) ? $converted : $str;
}
}