Valider un bbcode (ou autre) = html correct

Contenu du snippet

Ce petit script verifie simplement qu'un texte contenant un bbcode soit valide : qu'il y ait bien des balises ouvrantes et fermantes, et pas n'importe comment.
Ainsi, lorsque ce code sera parse er remplace par son equivalent html, il n'y aura pas de probleme de html crade (enfin, tout depend par quoi vous remplacez, evidemment ;-) )
Donc, voila ce que le code fait :
- detruit toute balise orpheline (balise ouvrante seule, balise fermante seule, balise fermante AVANT une balise ouvrante...)
- verifie que l'encapsulation est correcte. Sinon, la corrige. Exemple : [b][i] bla /b/i va devenir [b][i] bla /i/b (et ca, ca a ete complique ;-) )

Source / Exemple :


<?php
class verif_bb {
	
	//variables membres
	var $startTags;
	var $endTags;
	var $texte;
	var $startArr;
	var $endArr;
	
	//constructeur de la classe. Verifie que les parametres passes soient corrects. Accepte tableaux de meme taille ou chaines pour les tags, et une chaine uniquement pour le texte. Les tags ouvrants et leurs equivalents fermants DOIVENT avoir la meme clef dans leur tableau respectif.
	function verif_bb ($start, $end, &$chaine) {
		if (!is_string ($start) && !is_array ($start))
			die ('le parametre $start n\'est pas une chaine ou un tableau.');
		if (!is_string ($end) && !is_array ($end))
			die ('le parametre $end n\'est pas une chaine ou un tableau.');
		if (count ($start) != count ($end))
			die ('$start et $end ne sont pas de meme taille.');
		if (!is_string ($chaine))
			die ('le parametre $chaine n\'est pas une chaine.');
			
		$this -> startTags = $start;
		$this -> endTags = $end;
		$this -> texte = &$chaine;
		
		$this -> verif_integrite ();
	}
	
	//appelle les differentes methodes
	function verif_integrite () {
		$this -> strip_starting_end_tags ();
		$this -> strip_no_end_start ();
		if (is_array ($this -> startTags)) 
			$this -> verif_encaps();
	}
	
 //methode verifiant s'il y a des end tags avant leur equivalent start tag. Dans ce cas, on les vire!
	function strip_starting_end_tags () {
		//si on a un tableau de tags
		if (is_array ($this -> startTags)) {
			foreach ($this -> startTags as $clef => $val) {
				$endPos = strpos ($this -> texte, $this ->endTags[$clef]);
				$startPos = strpos ($this -> texte, $val);
				while ($endPos !== false && ($endPos < $startPos || $startPos === false)) {
					$this -> texte = substr_replace ($this -> texte, '', $endPos, strlen ($this -> endTags[$clef]));
					$endPos = strpos ($this -> texte, $this -> endTags[$clef]);
				}
			}
		}
		// si on a juste une chaine avec un tag
		else {
			$endPos = strpos ($this -> texte, $this -> endTags);
			$startPos = strpos ($this -> texte, $this -> startTags);
			while ($endPos !== false && ($endPos < $startPos || $startPos === false)) {
				$this -> texte = substr_replace ($this -> texte, '', $endPos, strlen ($this -> endTags));
				$endPos = strpos ($this -> texte, $this -> endTags);
			}
		}
	}
	
	//methode verifiant s'il y a en fin de texte des start tags sans end tags. dans ce cas, on les vire!
	function strip_no_end_start () {
		$this -> texte = strrev ($this -> texte);
		//si on a un tableau de tags
		if (is_array ($this -> startTags)) {
			foreach ($this -> startTags as $clef => $val) {
				$val =strrev ($val);
				$endPos = strpos ($this -> texte, strrev ($this -> endTags[$clef]));
				$startPos = strpos ($this -> texte, $val);
				while ($startPos !== false && ($endPos > $startPos || $endPos === false)) {
					$this -> texte = substr_replace ($this -> texte, '', $startPos, strlen ($val));
					$startPos = strpos ($this -> texte, $val);
				}
			}
		}
		// si on a juste une chaine avec un tag
		else {
			$endPos = strpos ($this -> texte, strrev ($this ->endTags));
			$startPos = strpos ($this -> texte, strrev ($this -> startTags));
			while ($startPos !== false && ($endPos > $startPos || $endPos === false)) {
				$this -> texte = substr_replace ($this -> texte, '', $startPos, strlen ($this -> startTags));
				$startPos = strpos ($this -> texte, strrev ($this ->startTags));
			}
		}
	$this -> texte = strrev($this -> texte);
	}
	
	//methode verifiant et corrigeant l'encapsulation des tags
	function verif_encaps () {
		if (isset ($this -> startArr))
			unset ($this -> startArr);
		if (isset ($this -> endArr))
			unset ($this -> endArr);
		foreach ($this -> startTags as $startVal) {
			$offset = 0;
			while (strpos ($this -> texte, $startVal, $offset) !== false) {
				$startPosTab = strpos ($this -> texte, $startVal, $offset);
				$this -> startArr[][$startVal] = $startPosTab;
				$offset = $startPosTab + strlen ($startVal);
			}
		}
		foreach ($this -> endTags as $clefVal => $endVal) {
			$offset = 0;
			$revTxt = strrev ($this -> texte);
			$revVal = strrev ($endVal);
			while (strpos ($revTxt, $revVal, $offset) !== false) {
				$endPosTab = strpos ($revTxt, $revVal, $offset);
				$this -> endArr[][$endVal]= strlen ($this -> texte) - $endPosTab -strlen ($endVal);
				$offset = $endPosTab + strlen ($endVal);
			}
		}

		$cpt = count ($this -> startArr);
		$iCpt = 0;
		while ($iCpt < $cpt) {
			$jCpt = $iCpt + 1;
			 while ($jCpt < $cpt) {
				foreach ($this -> startArr[$iCpt] as $clef => $val) {
					foreach ($this -> startArr[$jCpt] as $clef2 => $val2) {
						if ($clef  != $clef2) {
							$startPos = $val;
							$endPos = $this -> endArr[$iCpt][$this -> endTags[array_search($clef, $this -> startTags)]];
							$startPos2 = $val2;
							$endPos2 = $this -> endArr[$jCpt][$this -> endTags[array_search($clef2, $this -> startTags)]];
							if (($startPos < $startPos2 && $endPos < $endPos2) || ($startPos > $startPos2 && $endPos > $endPos2)) {
								$tagRep1 = $this -> endTags[array_search($clef, $this -> startTags)];
								$tagRep2 = $this -> endTags[array_search($clef2, $this -> startTags)];
								$len1 = strlen ($tagRep1);
								$len2 = strlen ($tagRep2);
								if ($len1 < $len2 && $endPos > $endPos2) {
									$endPos = $endPos - ($len2 - $len1);
									$this -> texte = str_pad ($this -> texte, $len2 - $len1);
								}
								if ($len1 > $len2 && $endPos > $endPos2) {
									$endPos = $endPos + ($len1 - $len2);
									$this -> texte = str_pad ($this -> texte, $len1 - $len2);
								}
								$this -> texte = substr_replace ($this -> texte, $tagRep1, $endPos2, $len2);
								$this -> texte = substr_replace ($this -> texte, $tagRep2, $endPos, $len1);
								$this -> verif_encaps ();
							}
						}
					}
				}
				$jCpt ++;
			}
			$iCpt ++;
		}
	}
	
}

// tests
$txt = '/url/i/b/b[b][i][b]bonjour/i/b/b[b]';
$txt2 = '[i][url][b] test /i/url/b';
$arrStart = array ('[b]', '[i]', '[url]');
$arrEnd = array ('/b', '/i', '/url');

$txttxt = '/b[b]bonjour/b[b][b]';
$txtStart = '[b]';
$txtEnd = '/b';

echo '<br> Avant : ', $txt, '<br/>';
$parser = new verif_bb($arrStart, $arrEnd, $txt);
echo '<br> Apres : ', $txt, '<br/>';

echo '<br> Avant : ', $txt2, '<br/>';
$parser = new verif_bb ($arrStart, $arrEnd, $txt2);
echo '<br> Apres : ', $txt2, '<br/>';

echo '<br> Avant : ', $txttxt, '<br/>';
$parser = new verif_bb ($txtStart, $txtEnd, $txttxt);
echo '<br> Apres : ', $txttxt, '<br/>';

?>

Conclusion :


Je n'ai pas tout a fait fini, je veux verifier que l'imbrication soit correcte, et faire la meme chose avec du html. Mais je n'ai plus le temps ce soir! Je mettrai a jour.

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.