note 44771 deleted from function.strip-tags by aharvey
| From: | aharvey@php.net | Date: | Thu, 20 Sep 2012 11:41:22 +0000 |
| Subject: | note 44771 deleted from function.strip-tags by aharvey | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-190904@lists.php.net to get a copy of this message | ||
Note Submitter: Isaac Schlueter php at isaacschlueter dot com
----
I am creating a rendering plugin for a CMS system (http://b2evolution.net) that wraps certain bits
of text in acronym tags. The problem is that if you have something like this:
<a href="http://www.php.net" title="PHP is
cool!">PHP</a>
then the plugin will mangle it into:
<a href="http://www.<acronym title="PHP:
Hypertext Processor">php</acronym>.net" title="<acronym title="PHP:
Hypertext Processor">PHP</acronym> is cool!>PHP</a>
This function will strip out tags that occur within other tags. Not super-useful in tons of
situations, but it was an interesting puzzle. I had started out using preg_replace, but it got
riduculously complicated when there were linebreaks and multiple instances in the same tag.
The CMS does its XHTML validation before the content gets to the plugin, so we can be pretty sure
that the content is well-formed, except for the tags inside of other tags.
<?php
if( !function_exists( 'antiTagInTag' ) )
{
// $content is the string to be anti-tagintagged, and $format sets the format of the internals.
function antiTagInTag( $content = '', $format = 'htmlhead' )
{
if( !function_exists( 'format_to_output' ) )
{ // Use the external function if it exists, or fall back on just strip_tags.
function format_to_output($content, $format)
{
return strip_tags($content);
}
}
$contentwalker = 0;
$length = strlen( $content );
$tagend = -1;
for( $tagstart = strpos( $content, '<', $tagend + 1 ) ; $tagstart !== false
&& $tagstart < strlen( $content ); $tagstart = strpos( $content, '<',
$tagend ) )
{
// got the start of a tag. Now find the proper end!
$walker = $tagstart + 1;
$open = 1;
while( $open != 0 && $walker < strlen( $content ) )
{
$nextopen = strpos( $content, '<', $walker );
$nextclose = strpos( $content, '>', $walker );
if( $nextclose === false )
{ // ERROR! Open waka without close waka!
// echo '<code>Error in antiTagInTag - malformed tag!</code> ';
return $content;
}
if( $nextopen === false || $nextopen > $nextclose )
{ // No more opens, but there was a close; or, a close happens before the next open.
// walker goes to the close+1, and open decrements
$open --;
$walker = $nextclose + 1;
}
elseif( $nextopen < $nextclose )
{ // an open before the next close
$open ++;
$walker = $nextopen + 1;
}
}
$tagend = $walker;
if( $tagend > strlen( $content ) )
$tagend = strlen( $content );
else
{
$tagend --;
$tagstart ++;
}
$tag = substr( $content, $tagstart, $tagend - $tagstart );
$tags[] = '<' . $tag . '>';
$newtag = format_to_output( $tag, $format );
$newtags[] = '<' . $newtag . '>';
$newtag = format_to_output( $tag, $format );
}
$content = str_replace($tags, $newtags, $content);
return $content;
}
}
?>