[php5 - dom - xpath] classe de pre-filtrage de texte

Description

Cette classe calcul un pourcentage d'apparition de certains mots pre-enregistre dans une base de donnees au format xml.
Les mots sont classes par categorie et la classe permet d'en ajouter ou d'en creer de nouvelles (pas d'effacement possible pour l'instant).
On peut utiliser cette classe pour valider une reponse dans un forum par exemple en recherchant le nombre de mots present dans la categorie 'insultes' (non presente dans le code, a creer vous meme donc) ou dans la categorie 'spamm' (avec des mots genre viagra, credits, financement... j'en passe et des meilleurs).
La fonction a utiliser est la fonction Filtre::Anaylse() qui renvoi un tableau avec pour cle le nom de chaque categorie et pour valeur le pourcentage d'apparition des mots presents dans chaque categorie (je sais pas si j'ai ete clair). La validation du texte transmis sera par contre gere par vos soins.

Le code est loin d'etre parfait (pas mal de boucle foreach() ) mais le temps d'execution reste bon, pas de probleme donc logiquement pour l'integration de cette classe dans vos projets. Un tableau de code d'erreurs est disponible mais etant donne qu'il n'y a que 2 focntions (en plus du constructeur), la gestion d'erreur est un peu particuliere.
J'ai essaye de commenter le code le plus possible mais n'hesitez pas a me demander de l'aide ou des renseignements, je le ferai avec plaisir :-)

Source / Exemple :


<?php
	/*
		|------------|
		| MODELE XML |
		|------------|
		
		<filtre>
			<cat1>
				<value>mot1</value>
				<value>mot2</value>
				<value>mot3</value>
				<value>mot4</value>
			</cat1>
			<cat2>
				<value>mot1</value>
				<value>mot2</value>
				<value>mot3</value>
				<value>mot4</value>
			</cat2>
			<cat3>
				<value>mot1</value>
				<value>mot2</value>
				<value>mot3</value>
				<value>mot4</value>
			</cat3>
		</filtre>		
		
		Auteur : IoNAce (jean84)
		Version PHP : 5
		Lib utilise : DOM & XPATH (incluses par defaut dans php5)
		Version classe : 1.4

  • /
class Filtre { /**********************/ /* Nom du fichier XML */ /**********************/ private $File; /*************************/ /* Handle du fichier XML */ /*************************/ private $Handle; /*********************************************/ /* Tableau d'erreurs renvoyees par la classe */ /*********************************************/ private static $TableOfErrors = array( 'CANT_CREATE_XML_FILE', 'CANT_LOAD_XML_FILE', 'LOAD_SUCCESS', 'CREATE_SUCCESS', 'CANT_OPEN_FILE', 'CANT_READ_FILE', 'CANT_SAVE_XML_FILE', 'NO_ERROR', 'CANT_SEPARATE_STRING' ); /********************************************************************************/ /* Rapport d'erreur de la classe */ /* A consulter pour connaitre le resutlat de certaines actions du constructeur */ /********************************************************************************/ public $LastError; /****************************************************************/ /* Constructeur de la classe */ /* Param 1 : $sNameOfFile */ /* -> Nom et path du fichier xml a charger (ou a creer) */ /****************************************************************/ function __construct($NameOfFile) { // Creation d'un nouvel handle $this->Handle = new DOMDocument('1.0', 'iso-8859-1'); $this->Handle->formatOutput = TRUE; // Si le fichier n'existe pas, on le cree if ( !file_exists((string)$NameOfFile) ) { $HandleDoc = $this->Handle; // Creation du noeud racine $Racine = $HandleDoc->createElement('filtre'); $Racine = $HandleDoc->appendChild($Racine); // On sauvegarde le fichier if ( $HandleDoc->save($NameOfFile) === FALSE ) $this->LastError = $this->TableOfErrors[0]; else $this->LastError = $this->TableOfErrors[3]; } else { // Sinon on le charge if ( !$this->Handle->load($NameOfFile) ) $this->LastError = $TableOfErrors[1]; else $this->LastError = $this->TableOfErrors[2]; } $this->File = $NameOfFile; } /************************************************************************************************************/ /* Fonction recherchant les mots de $LenWords caracteres afin de les enregistrer dans le fichier xml */ /* La fonction decoupe les mots grace aux espaces. Pensez donc a les inclures ! */ /* Param 1 : $String */ /* -> Chaine de caractere ou recuperer les mots */ /* Param 2 : $LenWords */ /* -> Nombre de caractere minimum par mot (si = 0, on recupere tout. Attention donc !) */ /* Param 3 : $Cat */ /* -> Nom de la categorie definissant le type de mots a enregistre */ /* Param 4 : $IsFile */ /* -> Si = TRUE, $String est le nom d'un fichier qu'il faudra lire en premier */ /* -> Par defaut, la valeur est mise a FALSE pour faire simple */ /* Attention a ne pas creer de categorie nommee 'foo' ou 'final', reserve a la classe ! */ /************************************************************************************************************/ public function SaveWords($String, $LenWords, $Cat, $IsFile=FALSE) { // Lecture du fichier if ( $IsFile ) { $File = fopen($String, 'r'); if ( $File === FALSE ) return $this->TableOfErrors[4]; $Buffer = fread($File, filesize($String)); if ( $Buffer === FALSE ) return $this->TableOfErrors[5]; fclose($File); $String = $Buffer; } $Compteur = 0; $Table = array(); $String = $this->Clean($String); $SubString = explode(' ', $String); if ( $SubString === FALSE ) return $this->TableOfErrors[8]; $NbrCases = count($SubString); for ( $i=0; $i<$NbrCases; $i++ ) { if ( strlen($SubString[$i]) >= $LenWords ) { if ( !empty($SubString[$i]) ) { $Table[$Compteur] = strtolower($SubString[$i]); $Compteur += 1; } } } // Recherche de la balise <$Cat> dans le fichier xml $XPath = new DOMXPath($this->Handle); $Query = "boolean(/filtre/$Cat) = false"; $Result = $XPath->evaluate($Query); $Handle = $this->Handle; $Handle->formatOutput = TRUE; if ( $Result === TRUE ) { // Recupere la racine $Racine = $Handle->getElementsByTagName('filtre')->item(0); $Categorie = $Handle->createElement($Cat); $Categorie = $Racine->appendChild($Categorie); // Sauvegarde du fichier if ( $Handle->save($this->File) === FALSE ) return $this->TableOfErrors[6]; } // Recupere la balise <$Cat> $Racine = $Handle->getElementsByTagName($Cat)->item(0); // On ajoute les elements foreach ( $Table as $Key => $Value ) { $Value = soundex($Value); // Verifie que le mot n'est pas deja enregistre $Query = '/filtre/*/word[@value="'.$Value.'"]'; $Result = $XPath->query($Query); if ( empty($Result->item(0)->nodeValue) ) { $BaliseElement = $Handle->createElement('word'); $BaliseElement = $Racine->appendChild($BaliseElement); $BaliseElement->setAttribute('value', $Value); } } // Sauvegarde du fichier if ( $Handle->save($this->File) === FALSE ) return $this->TableOfErrors[6]; else return $this->TableOfErrors[7]; } /****************************************************************************************************************************/ /* Cette fonction calcule (en pourcentage) le taux d'apparition de chaque mot et place le resultat dans un tableau. */ /* Le tableau renvoye index ses cases avec le nom des categories et le pourcentage de mots de cette catehorie comme valeur */ /* Param 1 : $String */ /* -> Texte a analyser */ /* Param 2 : $Cat */ /* -> Precise la categorie ou rechercher. Dans ce cas, le pourcentage ne sera calcule que pour cette categorie */ /* -> /!\ Si la categorie n'existe pas, le pourcentage sera toujours = 0 */ /* Dans le tableau renvoye, il y a une case speciale appellee 'foo' qui contient le nombre de mots trouvees par la fonction.*/ /* Permet de pouvoir apprehender le resultat final. Attention donc a ne pas creer de categorie 'foo' sous peine de voir le */ /* resultat errone. Une autre case appelle 'final' contient la somme de tous les pourcentages calcules jusque la. */ /****************************************************************************************************************************/ public function Analyse($String, $Cat=NULL) { // Preparation d'une instance de la classe DOMXPath $XPath = new DOMXPath($this->Handle); // Compteur de mots $Comtpeur = 0; // Preparation du tableau $Table = array(); if ( $Cat === NULL ) { $Query = '/filtre/*'; $Result = $XPath->query($Query); foreach ( $Result as $Key => $Value ) $Table[$Value->nodeName] = 0; } else { $Table[$Cat] = 0; } // Cree une case 'final' qu'on fait partir a 0 $Table['final'] = 0; $String = $this->Clean($String); // Exctraction des mots $SubString = explode(' ', $String); if ( $SubString === FALSE ) return $this->TableOfErrors[8]; $NbrCases = count($SubString); for ( $i=0; $i<$NbrCases; $i++ ) { if ( !empty($SubString[$i]) ) { $SubString[$i] = soundex($SubString[$i]); // On verifie que ce mot est enregistre dans une categorie (celle precise ou toutes) if ( $Cat === NULL ) $Query = '/filtre/*/word[@value="'.$SubString[$i].'"]'; else $Query = '/filtre/'.$Cat.'/word[@value="'.$SubString[$i].'"]'; $Result = $XPath->query($Query); if ( !empty($Result->item(0)->nodeValue) ) { // Si c'est le cas, on cherche les categories foreach ( $Table as $Key => $Value ) { $Query = '/filtre/'.$Key.'/word[@value="'.$SubString[$i].'"]'; $Result = $XPath->query($Query); // Si la categorie en cours contient bien la valeur obtenue if ( !empty($Result->item(0)->nodeValue) ) { $Table[$Key] += 1; break; } } } $Compteur += 1; } } // Calcul des pourcentages foreach ( $Table as $Key => $Value ) { if ( $Key != 'final' ) { if ( $Value != 0 ) $Table[$Key] = round((($Value * 100) / $Compteur), 2); $Table['final'] += $Table[$Key]; } } // Cree une case 'foo' permettant a l'utilisateur de conaitre le nombre de mots pris en compte par la fonction $Table['foo'] = $Compteur; // Retourne le tableau return $Table; } /************************************************/ /* Enleve la plupart des signes de ponctuation */ /* Param 1 : $Value */ /* -> Chaine a nettoyer */ /************************************************/ private function Clean($Table) { $Array = array(',', '!', ',', ';', '?', '*', '+', '-', '/', '²', '=', ')', '(', '{', '}', '"', '\'', '\\', '`', ':', ' '); return str_replace($Array, '', $Table); } } ?>

Conclusion :


Pas de bugs connus (je pense avoir fait le tour) mais pas de probleme pour les mises a jours si jamais vous en trouvez. Idem pour les fonctions a rajouter (je pense que je vais integre la possibilite d'effacer certains mots enregistres ou certaines categories, suivant les besoins).

Pour le niveau (mis en initie), j'ai fait ce choix car j'utilise XPath et DOM (de maniere simple). Que les debutants ne se frustrent pas, le code est tres accessible (de mon point de vue c'est vrai mais normalement y a pas trop de difficulte) et je reste de toute facon disponible.

En esperant que cela vous plaise :p

@++

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.