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
:
- Wrap a certain element pattern in a div.
- Add a class to a particular element.
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