0

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;
}

enter image description here enter image description here

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.