--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)