How to stop DOMDocument destroying embeds?

I am making use of PHP's DOMDocument to carry out two DOM operations on the post content, by filtering the_content:

The trouble is, it seems like DOMDocument is destroying embedded WordPress content like tweets. As seen in this example, the embedded tweet is not rendered as an iframe as it should be, it is just rendered using p.

Is there a way to stop DOMDocument from doing this?

My code is below.

/*
Wrap element in another element.
Contributed by @XzKto, https://stackoverflow.com/a/8428323/1375163
*/
function wrap_element($dom, $wrapped_element, $new_element) {
    // Initialise the new wrapper
    $wrapper = $dom-createElement($new_element);
    //Clone our created element
    $wrapper_clone = $wrapper-cloneNode();
    //Replace image with this wrapper div
    $wrapped_element-parentNode-replaceChild($wrapper_clone,$wrapped_element);
    //Append the element to wrapper div
    $wrapper_clone-appendChild($wrapped_element);
}

/*
Blockquote
*/
add_filter( 'the_content', 'bootstrap_blockquote' );
function bootstrap_blockquote( $content ) {
    // Load DOM of post content
    $dom = new DOMDocument();
    $dom-loadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    foreach($dom-getElementsByTagName('blockquote') as $blockquote){
        // Add blockquote class
        // Class addition contributed by @Gillu13, https://stackoverflow.com/a/63088684/1375163
        $class_to_add = 'blockquote';
        $blockquote-setAttribute('class', $class_to_add);
        // Wrap blockquote in figure
        wrap_element($dom, $blockquote, 'figure');
    }

    $content = utf8_decode($dom-saveHTML($dom-documentElement)); // formatting correction contributed by @Greeso, https://stackoverflow.com/a/20675396/1375163
    return $content;
}

..

/*
Original contributed by @jack,
https://stackoverflow.com/a/10683463/1375163
*/
add_filter( 'the_content', 'segment_post' );
function segment_post( $content ) {

    $d = new DOMDocument;
    libxml_use_internal_errors(true);
    $d-loadHTML($content);
    libxml_clear_errors();

    $segments = array(); $card = null;

    foreach ($d-getElementsByTagName('h3') as $h3) {
        // first collect all nodes
        $card_nodes = array($h3);
        // iterate until another h3 or no more siblings
        for ($next = $h3-nextSibling; $next  $next-nodeName != 'h3'; $next = $next-nextSibling) {
            $card_nodes[] = $next;
        }

        // create the wrapper node
        $card = $d-createElement('div');
        $card-setAttribute('class', 'card p-4 mb-3');

        // replace the h3 with the new card
        $h3-parentNode-replaceChild($card, $h3);
        // and move all nodes into the newly created card
        foreach ($card_nodes as $node) {
            $card-appendChild($node);
        }
        // keep title of the original h3
        $segments[] = $h3-nodeValue;
    }

    //  make sure we have segments (card is the last inserted card in the dom)
    /*
    if ($segments  $card) {
        $ul = $d-createElement('ul');
        foreach ($segments as $title) {
            $li = $d-createElement('li');

            $a = $d-createElement('a', $title);
            $a-setAttribute('href', '#');

            $li-appendChild($a);
            $ul-appendChild($li);
        }

        // add as sibling of last card added
        $card-parentNode-appendChild($ul);
    }
    */

    // TODO: examine https://stackoverflow.com/questions/10703057/wrap-all-html-tags-between-h3-tag-sets-with-domdocument-in-php

    $content = utf8_decode($d-saveHTML($d-documentElement)); // formatting correction contributed by @Greeso, https://stackoverflow.com/a/20675396/1375163    
    return $content;
}

Topic the-content filters Wordpress

Category Web

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.