Вы должны найти все теги открытыми, но не закрытыми, перед текстом заполнителя.
Вставьте новый текст, как вы делаете сейчас, а затем закройте теги.
Вот небрежный пример. Я думаю, что этот код будет работать со всем допустимым HTML, но я не уверен. И это, безусловно, примет недопустимую разметку. но все равно:
$h = '<p>The quick <a href="/">brown</a> fox jumps <!--more-->
over the <a href="/">lazy</a> dog.</p>';
$parts = explode("<!--more-->", $h, 2);
$front = $parts[0];
/* Find all opened tags in the front string */
$tags = array();
preg_match_all("|<([a-z][\w]*)(?: +\w*=\"[\\w/%&=]+\")*>|i", $front, $tags, PREG_OFFSET_CAPTURE);
array_shift($tags); /* get rid of the complete match from preg_match_all */
/* Check if the opened arrays have been closed in the front string */
$unclosed = array();
foreach($tags as $t) {
list($tag, $pos) = $t[0];
if(strpos($front, "</".$tag, $pos) == false) {
$unclosed[] = $tag;
}
}
/* Print the start, the replacement, and then close any open tags. */
echo $front;
echo "FOOBAR";
foreach($unclosed as $tag) {
echo "</".$tag.">";
}
Выходы
<p>The quick <a href="/">brown</a> fox jumps FOOBAR</p>