124 lines
3.3 KiB
PHP
124 lines
3.3 KiB
PHP
<?php
|
|
|
|
fof_add_item_filter('fof_balancetags');
|
|
|
|
/*
|
|
balanceTags
|
|
|
|
Balances Tags of string using a modified stack.
|
|
|
|
@param text Text to be balanced
|
|
@param force Forces balancing, ignoring the value of the option
|
|
@return Returns balanced text
|
|
@author Leonard Lin (leonard@acm.org)
|
|
@version v1.1
|
|
@date November 4, 2001
|
|
@license GPL v2.0
|
|
@notes
|
|
@changelog
|
|
--- Modified by Scott Reilly (coffee2code) 02 Aug 2004
|
|
1.2 ***TODO*** Make better - change loop condition to $text
|
|
1.1 Fixed handling of append/stack pop order of end text
|
|
Added Cleaning Hooks
|
|
1.0 First Version
|
|
*/
|
|
|
|
function fof_balancetags($text) {
|
|
|
|
$tagstack = array(); $stacksize = 0; $tagqueue = ''; $newtext = '';
|
|
|
|
# WP bug fix for comments - in case you REALLY meant to type '< !--'
|
|
$text = str_replace('< !--', '< !--', $text);
|
|
# WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
|
$text = preg_replace('#<([0-9]{1})#', '<$1', $text);
|
|
|
|
while (preg_match("/<(\/?\w*)\s*([^>]*)>/",$text,$regex)) {
|
|
$newtext .= $tagqueue;
|
|
|
|
$i = strpos($text,$regex[0]);
|
|
$l = strlen($regex[0]);
|
|
|
|
// clear the shifter
|
|
$tagqueue = '';
|
|
// Pop or Push
|
|
if ($regex[1][0] == "/") { // End Tag
|
|
$tag = strtolower(substr($regex[1],1));
|
|
// if too many closing tags
|
|
if($stacksize <= 0) {
|
|
$tag = '';
|
|
//or close to be safe $tag = '/' . $tag;
|
|
}
|
|
// if stacktop value = tag close value then pop
|
|
else if ($tagstack[$stacksize - 1] == $tag) { // found closing tag
|
|
$tag = '</' . $tag . '>'; // Close Tag
|
|
// Pop
|
|
array_pop ($tagstack);
|
|
$stacksize--;
|
|
} else { // closing tag not at top, search for it
|
|
for ($j=$stacksize-1;$j>=0;$j--) {
|
|
if ($tagstack[$j] == $tag) {
|
|
// add tag to tagqueue
|
|
for ($k=$stacksize-1;$k>=$j;$k--){
|
|
$tagqueue .= '</' . array_pop ($tagstack) . '>';
|
|
$stacksize--;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
$tag = '';
|
|
}
|
|
} else { // Begin Tag
|
|
$tag = strtolower($regex[1]);
|
|
|
|
// Tag Cleaning
|
|
|
|
// If self-closing or '', don't do anything.
|
|
if((substr($regex[2],-1) == '/') || ($tag == '')) {
|
|
}
|
|
// ElseIf it's a known single-entity tag but it doesn't close itself, do so
|
|
elseif ($tag == 'br' || $tag == 'img' || $tag == 'hr' || $tag == 'input') {
|
|
$regex[2] .= '/';
|
|
} else { // Push the tag onto the stack
|
|
// If the top of the stack is the same as the tag we want to push, close previous tag
|
|
if (($stacksize > 0) && ($tag != 'div') && ($tagstack[$stacksize - 1] == $tag)) {
|
|
$tagqueue = '</' . array_pop ($tagstack) . '>';
|
|
$stacksize--;
|
|
}
|
|
$stacksize = array_push ($tagstack, $tag);
|
|
}
|
|
|
|
// Attributes
|
|
$attributes = $regex[2];
|
|
if($attributes) {
|
|
$attributes = ' '.$attributes;
|
|
}
|
|
$tag = '<'.$tag.$attributes.'>';
|
|
//If already queuing a close tag, then put this tag on, too
|
|
if ($tagqueue) {
|
|
$tagqueue .= $tag;
|
|
$tag = '';
|
|
}
|
|
}
|
|
$newtext .= substr($text,0,$i) . $tag;
|
|
$text = substr($text,$i+$l);
|
|
}
|
|
|
|
// Clear Tag Queue
|
|
$newtext .= $tagqueue;
|
|
|
|
// Add Remaining text
|
|
$newtext .= $text;
|
|
|
|
// Empty Stack
|
|
while($x = array_pop($tagstack)) {
|
|
$newtext .= '</' . $x . '>'; // Add remaining tags to close
|
|
}
|
|
|
|
// WP fix for the bug with HTML comments
|
|
$newtext = str_replace("< !--","<!--",$newtext);
|
|
$newtext = str_replace("< !--","< !--",$newtext);
|
|
|
|
return $newtext;
|
|
}
|
|
?>
|