Решил вопрос вот так:
static public function create_dom($string = null) {
$dom = new DOMDocument();
// ----------------------------------------------------------------
// Делается обертка в виде <div> для $string. Это нужно, так как из-за LIBXML_HTML_NOIMPLIED теги могут выводиться несколько некорректно. Подробности по ссылке:
// https://stackoverflow.com/questions/29493678/loadhtml-libxml-html-noimplied-on-an-html-fragment-generates-incorrect-tags
// Также добавляется кодировка - так как без вместо текста, полученного от ckeditor, будут кракозябры.
// ----------------------------------------------------------------
$dom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . '<div>' . $string . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$container = $dom->getElementsByTagName('div')->item(0);
$container = $container->parentNode->removeChild($container);
while ($dom->firstChild) {
$dom->removeChild($dom->firstChild);
}
while ($container->firstChild) {
$dom->appendChild($container->firstChild);
}
return $dom;
}
static public function unwrap_tags($string, $tags) {
$dom = static::create_dom($string);
foreach ($dom->childNodes as $c) {
if (in_array($c->tagName, $tags)) {
// если просто добавить в $result $c->nodeValue, то не добавятся внутренние теги (<br>, например), ведь их нет в nodeValue.
foreach ($c->childNodes as $cc) {
$result .= $cc->ownerDocument->saveHTML($cc);
}
} else {
$result .= $c->ownerDocument->saveHTML($c);
}
}
return $result;
}
static public function prepare_text($text) {
$text = static::unwrap_tags($text, array('p', 'div', 'span'));
return $text;
}
Вроде все работает.