phpwordpresssvgwpengine

PHP Warning: simplexml_load_file(): I/O warning : failed to load external entity Wordpress WP Engine


At WP Engine, our prod and staging Wordpress environments both are running PHP 8.0.

Using WP Engine dashboard, I automatically copied prod to staging and was ready to start on a new feature but immediately, I saw a new entry in the staging debug log that had never been present on the prod site/log. I haven't been able to move forward as I have checked it is an exact copy of the site and WP Engine confirmed the site environments are identical (php.ini etc.)

    PHP Warning:  simplexml_load_file(): I/O warning : failed to load 
    external entity 
    /wp-content/uploads/2021/11/Group-345.svg; 
    in /nas/content/live/ecistage/wp- 
    content/themes/deci/inc/helpers.php 
    on line 246

helpers.php

The previous developers who created the Wordpress theme built it using ACF Flexible Content. The error is related to a helper function that gets SVG real size (width+height / viewbox) and uses it in width, height attr.

    function fix_wp_get_attachment_image_svg( $image, $attachment_id, $size, $icon ) {
        if ( is_array( $image ) && preg_match( '/\.svg$/i', $image[0] ) ) {
            if ( is_array( $size ) ) {
                $image[1] = $size[0];
                $image[2] = $size[1];
            } elseif ( ( $xml = simplexml_load_file( $image[0] ) ) !== false ) {
                $attr     = $xml->attributes();
                $viewbox  = explode( ' ', $attr->viewBox );
                $image[1] = isset( $attr->width ) && preg_match( '/\d+/', $attr->width, $value ) ? (int) $value[0] : ( count( $viewbox ) == 4 ? (int) $viewbox[2] : null );
                $image[2] = isset( $attr->height ) && preg_match( '/\d+/', $attr->height, $value ) ? (int) $value[0] : ( count( $viewbox ) == 4 ? (int) $viewbox[3] : null );
            } else {
                $image[1] = $image[2] = null;
            }
        }
        return $image;
    }

    add_filter( 'wp_get_attachment_image_src', 'fix_wp_get_attachment_image_svg', 10, 4 );

Line 246 is the elseif statement:

    } elseif ( ( $xml = simplexml_load_file( $image[0] ) ) !== false ) {

Content of Group-34.svg

https://gist.github.com/billiemead/c0d1a2703cdac8f4423b9ddd93cfcca7?short_path=5a8a6c7

So far I have:
• checked that php_xml is being loaded
• checked that allow_url_fopen in php.ini is on
• allow_url_include is on
• created simplexml.php with the following content:

    <?php
 
    if (function_exists('simplexml_load_file')) {
        echo "simpleXML functions are available.<br />\n";
    } else {
        echo "simpleXML functions are not available.<br />\n";
    }

And it did return

simpleXML functions are available


Solution

  • I faced the same issue. In my case my website was on an Azure server. When I migrated the development site to live(Azure Managed WP plan), I faced the same issue.

    This issue was due to the Image path.

    Some of the Managed WordPress hosting are configured to use RELATIVE URLs for Images instead of ABSOLUTE URL.

    In this below line of code, It checks the Image URL. In my/our case this condition itself will fail because relative path returns 404 without as it's without site_url.

    } elseif ( ( $xml = simplexml_load_file( $image[0] ) ) !== false ) {
    

    To ensure that this is the case, you can try adding site_url (Website URL) before the Image URL like below in the first line of the function.

    $image[0] = site_url().$image[0];
    

    After doing this change if the function works then it has to be an issue due to the Image URL(relative/absolute).

    If you check the wp-config.php , you can find the below line of code which changes the Images to be displayed in Relative path (/wp-content/uploads/2022/01/filename-png) instead of Absolute path (www.sitename.com/wp-content/uploads/2022/01/filename-png)

    define('WP_CONTENT_URL', '/wp-content');
    

    This issue can be fixed by commenting this code in wp-config.php

    Also, make sure to delete the code which you added to your function to add site_url to the beginning of image path.