1

I have used this function to add a responsive class to all the images in content but this breaks the html structure of the website. This wraps the content with : <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><body> the content goes here (output from the_content();) </body></html>

function add_responsive_class($content)
{
    $content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
    if (!empty($content)) {
        $document = new DOMDocument();
        libxml_use_internal_errors(true);
        $document->loadHTML(utf8_decode($content));

        $imgs = $document->getElementsByTagName('img');
        foreach ($imgs as $img) {
            $classes = $img->getAttribute('class');
            $img->setAttribute('class', $classes . ' img-fluid');
        }

        $html = $document->saveHTML();
        return $html;
    }
}
add_filter('the_content', 'add_responsive_class');
add_filter('acf_the_content', 'add_responsive_class');

Can i know why? any alternative solution for this?

2 Answers 2

1

Parsing and modifying HTML properly using the standard PHP library is quite a pain. There are many gotchas. Here's a well documented example that will add the img-fluid class to all images in the content.

To ensure that the doctype and HTML tags are not added to the HTML fragment a solution from this StackOverflow answer is used:

$dom->loadHTML( $content ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

Note that there are other ways of doing this which are discussed in the SO post I linked to, but this soltion has worked well for me.

The code I've posted below expands on this solution to deal with utf8 characters as well.

/**
 * Adds img-fluid class to images in content.
 * Fire late to affect gallery images.
 */
add_filter( 'the_content',     'add_responsive_class', 9999 );
add_filter( 'acf_the_content', 'add_responsive_class', 9999 );
function add_responsive_class( $content ) {
    // Bail if there is no content to work with.
    if ( ! $content ) {
        return $content;
    }

    // Create an instance of DOMDocument.
    $dom = new \DOMDocument();

    // Supress errors due to malformed HTML.
    // See http://stackoverflow.com/a/17559716/3059883
    $libxml_previous_state = libxml_use_internal_errors( true );

    // Populate $dom with $content, making sure to handle UTF-8, otherwise
    // problems will occur with UTF-8 characters.
    // Also, make sure that the doctype and HTML tags are not added to our HTML fragment. http://stackoverflow.com/a/22490902/3059883
    $dom->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

    // Restore previous state of libxml_use_internal_errors() now that we're done.
    libxml_use_internal_errors( $libxml_previous_state );

    // Create an instance of DOMXpath.
    $xpath = new \DOMXpath( $dom );

    // Get images.
    $imgs = $xpath->query( "//img" );

    // Add additional classes to images.
    foreach ( $imgs as $img ) {
        $existing_class = $img->getAttribute( 'class' );
        $img->setAttribute( 'class', "{$existing_class} img-fluid" );
    }

    // Save and return updated HTML.
    $new_content = $dom->saveHTML();
    return $new_content;
}
7
  • You got it, @LatheeshVMVilla! Commented Dec 22, 2018 at 21:31
  • hi i am getting a warning with debug on : DOMDocument::loadHTML() expects parameter 2 to be integer, string given -> Any way to fix it ?
    – user145078
    Commented Dec 26, 2018 at 13:16
  • 1
    Hi @LatheeshVMVilla, I have not reproduced the warning and have tested (and double tested) this code. Did you copy the code I posted exactly? It sounds like you're having trouble with the line $dom->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); specifically the bitwise or operation applied to the configuration constants (which should both be integers per the docs) at the end of the line: LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD. Commented Dec 26, 2018 at 16:29
  • 1
    i came to know why this happended..it's because of php version ..in one hosting the php version was like 5.x some thing and in another one it was 7.x. the code works fine in 7.x
    – user145078
    Commented Dec 26, 2018 at 19:19
  • 1
    Hi, I think 5.5: https://stackoverflow.com/questions/40911718/domdocumentloadhtml-expects-parameter-2-to-be-long-string-given-when-trying ---- is it possible to provide a fallback? is it usually done?
    – user145078
    Commented Dec 26, 2018 at 19:44
1

If you are using bootstrap and want a responsive image in the_content(). You may try this code; works fine in my case img-fluid. You can replace it with your own class.

function add_image_responsive_class($content) {
    global $post;
    
    $pattern ="/<img(.*?)class=\"(.*?)\"(.*?)>/i";
    $replacement = '<img$1class="$2 img-fluid"$3>';
    $content = preg_replace($pattern, $replacement, $content);
    
    return $content;
}
add_filter('the_content', 'add_image_responsive_class');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.