#StackBounty: Set media metadata (i.e. "dimensions" field) on SVG file after extracting it with a filter

Bounty: 50

My question is about how to attached the size dimensions I have successfully extracted from an SVG and force them into the WP ‘dimensions’ field associated with the file, so that the dimensions appear in the media library.

Note: this is not the same as this earlier question I posted. In that question, I asked how to extract the dimension value However, no one figured out how to set that value permanently to the SVG so it would display in the media library.

Where I extract the dimesions

I extract the image dimensions from SVGs using a filter. This filter allows me to display the SVGs, not just as logos, but as featured images. The filter I use identifies the size of the SVG from inside the SVG file and then resets the values of image[1] and $image[2] values in the array returned by
wp_get_attachment_image_src() This is that function:

File: wp-includes/media.php
804: /**
805:  * Retrieve an image to represent an attachment.
806:  *
807:  * A mime icon for files, thumbnail or intermediate size for images.
808:  *
809:  * The returned array contains four values: the URL of the attachment image src,
810:  * the width of the image file, the height of the image file, and a boolean
811:  * representing whether the returned array describes an intermediate (generated)
812:  * image size or the original, full-sized upload.
813:  *
814:  * @since 2.5.0
815:  *
816:  * @param int          $attachment_id Image attachment ID.
817:  * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
818:  *                                    and height values in pixels (in that order). Default 'thumbnail'.
819:  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
820:  * @return false|array Returns an array (url, width, height, is_intermediate), or false, if no image is available.
821:  */
822: function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
823:    // get a thumbnail or intermediate image if there is one
824:    $image = image_downsize( $attachment_id, $size );
825:    if ( ! $image ) {
826:        $src = false;
827: 
828:        if ( $icon && $src = wp_mime_type_icon( $attachment_id ) ) {
829:            /** This filter is documented in wp-includes/post.php */
830:            $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
831: 
832:            $src_file = $icon_dir . '/' . wp_basename( $src );
833:            @list( $width, $height ) = getimagesize( $src_file );
834:        }
835: 
836:        if ( $src && $width && $height ) {
837:            $image = array( $src, $width, $height );
838:        }
839:    }

This is the filter that I apply to that function, which changes the values of $image[1] and $image[2] (i.e. the image width and height, respectively).

 add_filter( 'wp_get_attachment_image_src', 'fix_wp_get_attachment_image_svg', 10, 4 );  /* the hook */

 function fix_wp_get_attachment_image_svg($image, $attachment_id, $size, $icon) {
    if (is_array($image) && preg_match('/.svg$/i', $image[0]) && $image[1] <= 1) {
        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;
} 

Filter works, but media library doesn’t show extracted data

The filter works, and from what I can tell this information in $image[1] and $image[2] are being assigned to the html width and height of the element of the placed SVG. But, as you can see in the image below, the filter doesn’t seem to be updating the image’s dimensions field in the WP database.

library view of SVG vs PNG

My question summarized:

How do I take these dimension values, that my filter retrieves, and get them attached to the image file in the database itself in a way that allows me to view the dimensions in the media library?

Thanks!!


Get this bounty!!!

Leave a Reply