Bonjour,
Cette classe permet de couper une chaîne de caractère à une longueur donnée. La chaîne sera coupée entre deux mots et en dehors d'une balise.
Toutes les balises qui sont restées ouverte sont refermées à la fin de la chaîne.
Les balises ne sont pas exclues du calcul du nombre de caractères.
La classe gère les balises de type <br /> (qui n'ont qu'une seul balise).
Avec la généralisation des éditeurs wysiwyg qui retournent du texte html, ce genre de script devrait être de plus en plus rependu.
Exemple :
<p>Lorem ipsum <i>dolor</i> sit amet, <b>consec tetuer adipiscing elit</b></p>.
<p>Lorem ipsum <i>dolor</i> sit amet, <b>consec</b></p>
Source / Exemple :
<?php
class HtmlString {
/*
Chaine d'origine
private $strChaineOrigine;
/*
Chaine coupée à la longueur donnée
private $strChaineCoupee;
/*
Caractère ou doit se faire la césure
Par défaut, un espace
private $strCaractereCesure = ' ';
/*
Messages d'erreur
private $strErreur;
/*
Position de la césure
private $intCesurePos;
/*
Position du dernier espace de la chaine coupée
private $intDernierCaracCesure;
/*
Valeur de décrémentation de la taille de la chaine si on est dans une balise
private $intDecrementationCesurePos = 5;
/*
Indique si la césure est bien faite en dehors d'une balise
Par défaut on considère qu'elle est effectuée au milieu d'une balise
private $blnCesureHorsBalise = 0;
/*
Indique si la chaine est plus courte que la longueur de césure
Par défaut la chaine est plus longue
private $blnChaineTropCourte = 0;
/*
Pile des balises ouvertes
private $t_strBalisesOuvertes;
function __construct($strChaineOrigine, $intCesurePos) {
$this->strChaineOrigine = $strChaineOrigine;
$this->intCesurePos = $intCesurePos;
}
function SetParams($strCaractereCesure, $intDecrementationCesurePos) {
$this->strCaractereCesure = $strCaractereCesure;
$this->intDecrementationCesurePos = $intDecrementationCesurePos;
}
/*
Coupe la chaine d'origine au dernier espace avant la longueur voulue
private function CouperChaine(){
/* Coupe la chaine à la longuer maximale */
$this->strChaineCoupee = substr($this->strChaineOrigine, 0, $this->intCesurePos);
/* Extrait la position du dernier caractère de césure de la chaine coupée */
$this->intDernierCaracCesure = strrpos($this->strChaineCoupee, $this->strCaractereCesure);
/* Si le caractère de césure a été trouvé */
if($this->intDernierCaracCesure)
/* Coupe la chaine au dernier espace de sa longueur maximale */
$this->strChaineCoupee = substr($this->strChaineOrigine, 0, $this->intDernierCaracCesure);
}
/*
Vérifie que la césure n'aie pas été effectuée au milieu d'une balise
private function VerifierCesure() {
/* Parcours toute la chaine depuis la fin */
for($i=strlen($this->strChaineCoupee)-1; $i>=0; $i--) {
/* Si on tombe sur une fermeture de balise */
if($this->strChaineCoupee[$i] == '>' && $this->strChaineCoupee[$i-1] != '\\') {
/* Alors on est pas dans une balise */
$this->blnCesureHorsBalise = 1;
break;
}
/* Si on tombe sur une ouverture de balise, alors on est dans une balise */
elseif($this->strChaineCoupee[$i] == '<' && $this->strChaineCoupee[$i-1] != '\\') {
/* On le respécifie même si la valeur est censée être à 0 */
$this->blnCesureHorsBalise = 0;
break;
}
/* Si c'est le premier caractère de la chaine */
if($i==0)
/* Alors c'est qu'il n'y avait pas de balises du tout */
$this->blnCesureHorsBalise = 1;
}
}
/*
Vérifie que la chaine soit plus longue que la position de césure
private function VerifierLongueurChaine(){
/* Si la chaine est vide */
if(strlen($this->strChaineOrigine) == 0)
/* Indiquer que la chaine est trop courte */
$this->blnChaineTropCourte = 1;
/* Si la chaine est plus petite que la position de césure */
elseif(strlen($this->strChaineOrigine) <= $this->intCesurePos)
/* Indiquer que la chaine est trop courte */
$this->blnChaineTropCourte = 1;
/* Si la chaine est plus grande */
else
/* Indiquer que la chaine n'est pas trop courte */
$this->blnChaineTropCourte = 0;
}
/*
Obtient la chaine coupée à un espace en dehors d'une balise
private function ObtenirChaineCoupeeJuste() {
/* Tant que la césure n'est pas effectuée en dehors d'une balise */
while(!$this->blnCesureHorsBalise) {
/* Couper la chaine */
$this->CouperChaine();
/* Réduire la longueur de la chaine coupée */
if($this->intCesurePos - $this->intDecrementationCesurePos >= 0) {
$this->intCesurePos -= $this->intDecrementationCesurePos;
}
/* Si on a réduit la position de césure au point de couper toute la chaine, on affiche une erreur */
/* Peut arriver si la position de césure est courte et qu'il y a une très longue balise au début */
else {
$this->strErreur = 'Erreur : la position de la césure est trop courte par rapport à la taille de la chaine.';
break;
}
$this->VerifierCesure();
}
}
private function TrouverBalises() {
/* Place toutes les balises ouvrantes dans un tableau */
$strBalisesOuvrantes = preg_match_all('|<([a-z]+)[^>]*>|i', $this->strChaineCoupee, $t_strBalisesOuvrantes);
/* Place le résultat dans le tableau de la classe */
$this->t_strBalisesOuvertes = $t_strBalisesOuvrantes[1];
/* Place toutes les balises fermantes dans un tableau */
$strBalisesFermantes = preg_match_all('|</([a-z]+)[^>]*>|i', $this->strChaineCoupee, $t_strBalisesFermantes);
/* Inverse le tableau des balises ouvrantes (vu qu'elles doivent se fermer en ordre inverse) */
$this->t_strBalisesOuvertes = array_reverse($this->t_strBalisesOuvertes);
/* Parcours le tableau des balises fermantes */
foreach($t_strBalisesFermantes[1] as $Index => $strBaliseFermante) {
/* Parcours le tableau des balises ouvrantes */
foreach($this->t_strBalisesOuvertes as $Index => $strBaliseOuvrante) {
/* Si le nom de la balise est identique */
if($strBaliseOuvrante == $strBaliseFermante) {
/* Supprime la balise de la liste des balises ouvrantes */
unset($this->t_strBalisesOuvertes[$Index]);
break;
}
}
}
}
private function FermerBalises() {
/* Pour chaque balise ouverte restante */
foreach($this->t_strBalisesOuvertes as $strBaliseOuverte)
/* Ferme la balise */
$this->strChaineCoupee .= '</' . $strBaliseOuverte . '>';
}
public function ExecuterCoupe() {
$this->VerifierLongueurChaine();
if(!$this->blnChaineTropCourte) {
$this->ObtenirChaineCoupeeJuste();
$this->TrouverBalises();
$this->FermerBalises();
$strRetour = $this->strChaineCoupee;
}
else {
$strRetour = $this->strChaineOrigine;
}
if(strlen($this->strErreur) > 2)
return $this->strErreur;
else
return $strRetour;
}
}
?>
Conclusion :
Il y a encore beaucoup d'améliorations à y apporter, dans la gestion des caractères échappés par exemple (\< ne doit pas être considéré comme balise si magic_quotes est activé)
C'est mon premier script en php orienté objet, donc il y a sûrement pas mal de choses a améliorer, n'hésitez surtout pas à faire des critiques.