--TEST--
Bug #76738 Wrong handling of output buffer
--SKIPIF--
--FILE--
on_load($test_string);
var_dump($after_load === $test_string);
final class rh_rte_helper_debug
{
public $errors = [];
public function on_load(string $content): string
{
$content = utf8_encode($content);
$content = $this->add_outer_html($content);
$content = $this->remove_garbage($content);
$has_root_block = $this->has_root_block($content);
if(!$has_root_block)
{
$content = $this->add_root_block($content);
}
$content = $this->remove_outer_html($content);
$content = mb_convert_encoding($content, 'html-entities', 'UTF-8');
$content = utf8_decode($content);
return $content;
}
private function has_root_block(string $content): bool
{
$return = $content;
$doc = $this->get_dom($content);
if($doc != FALSE)
{
$xpath = ($doc != FALSE) ? new DomXpath($doc) : FALSE;
if($xpath != FALSE)
{
$path = '//*[contains(concat(" ", normalize-space(@class), " "), "tinymce-generated-root-block")]';
$nodes = $xpath->query($path);
$nodes_idx = ($nodes != FALSE) ? $nodes->length : 0;
if($nodes_idx > 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
}
private function add_root_block(string $content): string
{
$return = $content;
$doc = $this->get_dom($content);
if($doc != FALSE)
{
$xpath = ($doc != FALSE) ? new DomXpath($doc) : FALSE;
if($xpath != FALSE)
{
$path = '//*[contains(concat(" ", normalize-space(@class), " "), "tinymce-generated-root-block")]';
$nodes = $xpath->query($path);
$nodes_idx = ($nodes != FALSE) ? $nodes->length : 0;
if($nodes_idx == 0)
{
$root_div = $doc->createElement('div');
$root_div->setAttribute('class', 'tinymce-generated-root-block');
$root_div->setAttribute('style', 'margin: 0px; padding: 0px;');
$body = $doc->getElementsByTagName('body')->item(0);
if($body !== NULL)
{
while($body->childNodes->length > 0)
{
$root_div->appendChild($body->childNodes->item(0));
}
$body->appendChild($root_div);
$return = $doc->saveHTML();
}
}
}
}
return $return;
}
private function add_outer_html(string $content): string
{
return '
Tidy' . $content . '';
}
private function remove_root_block(string $content): string
{
return $this->remove_block($content, 'tinymce-generated-root-block');
}
private function remove_garbage(string $content): string
{
return $this->remove_block($content, 'tinymce-garbage-root-block');
}
private function get_dom(string $html, bool $add_outer_html=TRUE): DOMDocument
{
$use_internal_errors = libxml_use_internal_errors(TRUE);
$dom = new DOMDocument;
$dom->resolveExternals = FALSE;
$dom->preserveWhiteSpace = TRUE;
$dom->strictErrorChecking = FALSE;
$dom->formatOutput = TRUE;
$dom->recover = TRUE;
$dom->validateOnParse = TRUE;
$dom->substituteEntities = FALSE;
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
$options = 0;
if(!$add_outer_html)
{
$options = LIBXML_HTML_NOIMPLIED;
}
$options = $options | LIBXML_HTML_NODEFDTD;
$loaded = @$dom->loadHTML('' . $html, $options);
if(!$loaded)
{
$dom = FALSE;
$this->errors = libxml_get_errors();
}
else
{
foreach($dom->childNodes as $item)
{
if($item->nodeType == XML_PI_NODE)
{
$dom->removeChild($item);
}
}
$dom->encoding = 'UTF-8';
}
libxml_clear_errors();
libxml_use_internal_errors($use_internal_errors);
return $dom;
}
private function remove_outer_html(string $content): string
{
$return = $content;
$doc = $this->get_dom($content);
if($doc !== FALSE)
{
if($doc->doctype !== NULL)
{
$doc->doctype->parentNode->removeChild($doc->doctype);
}
$html = $doc->getElementsByTagName('html')->item(0);
if($html !== NULL)
{
$fragment = $doc->createDocumentFragment();
while($html->childNodes->length > 0)
{
$childNode = $html->childNodes->item(0);
$fragment->appendChild($childNode);
}
$html->parentNode->replaceChild($fragment, $html);
}
$body = $doc->getElementsByTagName('body')->item(0);
if($body !== NULL)
{
$return = '';
$fragment = $doc->createDocumentFragment();
while($body->childNodes->length > 0)
{
$childNode = $body->childNodes->item(0);
$fragment->appendChild($childNode);
$return .= $doc->saveHTML($childNode);
}
$body->parentNode->replaceChild($fragment, $body);
}
else
{
$return = $doc->saveHTML();
}
}
return $return;
}
private function remove_block(string $content, string $class='tinymce-generated-root-block'): string
{
$return = $content;
$doc = $this->get_dom($content);
if($doc != FALSE)
{
$xpath = ($doc != FALSE) ? new DomXpath($doc) : FALSE;
if($xpath != FALSE)
{
$path = '//*[contains(concat(" ", normalize-space(@class), " "), "'.$class.'")]';
$nodes = $xpath->query($path);
$nodes_idx = ($nodes != FALSE) ? $nodes->length : 0;
if($nodes_idx > 0)
{
foreach($nodes as $node)
{
$fragment = $doc->createDocumentFragment();
while($node->childNodes->length > 0)
{
$childNode = $node->childNodes->item(0);
if($childNode->nodeType == XML_TEXT_NODE)
{
$fragment->appendChild($doc->createTextNode($childNode->nodeValue));
$childNode->parentNode->removeChild($childNode);
}
else
{
$fragment->appendChild($childNode);
}
}
$node->parentNode->replaceChild($fragment, $node);
}
$return = $doc->saveHTML();
}
}
}
return $return;
}
}
--EXPECT--
bool(true)