Make WordPress Core


Ignore:
Timestamp:
06/30/2020 07:28:07 PM (5 years ago)
Author:
flixos90
Message:

Media: Introduce wp_img_tag_add_width_and_height_attr() to add dimension attributes to images.

Following up on [48170], this changeset moves the new logic to add missing img dimension attributes into a separate function that is run first within wp_filter_content_tags(). It also adds a utility function wp_image_src_get_dimensions() with logic reused from wp_image_add_srcset_and_sizes(), and it ensures that width and height attributes only get added if both of the attributes are missing on the original img tag.

This changeset furthermore improves test coverage and separates tests for the different aspects of img tag modification.

Props azaozz.
Fixes #50367. See #44427.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/media.php

    r48198 r48237  
    14931493
    14941494/**
     1495 * Determines an image's width and height dimensions based on the source file.
     1496 *
     1497 * @since 5.5.0
     1498 *
     1499 * @param string $image_src  The image source file.
     1500 * @param array  $image_meta The image meta data as returned by 'wp_get_attachment_metadata()'.
     1501 * @return array|false Array with first element being the width and second element being the height,
     1502 *                     or false if dimensions cannot be determined.
     1503 */
     1504function wp_image_src_get_dimensions( $image_src, $image_meta ) {
     1505    $image_filename = wp_basename( $image_src );
     1506
     1507    if ( wp_basename( $image_meta['file'] ) === $image_filename ) {
     1508        return array(
     1509            (int) $image_meta['width'],
     1510            (int) $image_meta['height'],
     1511        );
     1512    }
     1513
     1514    foreach ( $image_meta['sizes'] as $image_size_data ) {
     1515        if ( $image_filename === $image_size_data['file'] ) {
     1516            return array(
     1517                (int) $image_size_data['width'],
     1518                (int) $image_size_data['height'],
     1519            );
     1520        }
     1521    }
     1522
     1523    return false;
     1524}
     1525
     1526/**
    14951527 * Adds 'srcset' and 'sizes' attributes to an existing 'img' element.
    14961528 *
    14971529 * @since 4.4.0
    1498  * @since 5.5.0 `width` and `height` are now added if not already present.
    14991530 *
    15001531 * @see wp_calculate_image_srcset()
     
    15271558    }
    15281559
    1529     $attr = '';
    1530 
    15311560    $width  = preg_match( '/ width="([0-9]+)"/', $image, $match_width ) ? (int) $match_width[1] : 0;
    15321561    $height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
    15331562
    1534     if ( ! $width || ! $height ) {
    1535         /*
    1536          * If attempts to parse the size value failed, attempt to use the image meta data to match
    1537          * the image file name from 'src' against the available sizes for an attachment.
    1538          */
    1539         $image_filename = wp_basename( $image_src );
    1540 
    1541         if ( wp_basename( $image_meta['file'] ) === $image_filename ) {
    1542             $width  = (int) $image_meta['width'];
    1543             $height = (int) $image_meta['height'];
    1544         } else {
    1545             foreach ( $image_meta['sizes'] as $image_size_data ) {
    1546                 if ( $image_filename === $image_size_data['file'] ) {
    1547                     $width  = (int) $image_size_data['width'];
    1548                     $height = (int) $image_size_data['height'];
    1549                     break;
    1550                 }
    1551             }
    1552         }
    1553 
    1554         if ( ! $width || ! $height ) {
     1563    if ( $width && $height ) {
     1564        $size_array = array( $width, $height );
     1565    } else {
     1566        $size_array = wp_image_src_get_dimensions( $image_src, $image_meta );
     1567        if ( ! $size_array ) {
    15551568            return $image;
    15561569        }
    1557 
    1558         // Add width and height if not present.
    1559         $attr .= ' ' . trim( image_hwstring( $width, $height ) );
    1560     }
    1561 
    1562     $size_array = array( $width, $height );
    1563     $srcset     = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
     1570    }
     1571
     1572    $srcset = wp_calculate_image_srcset( $size_array, $image_src, $image_meta, $attachment_id );
    15641573
    15651574    if ( $srcset ) {
     
    15741583    if ( $srcset && $sizes ) {
    15751584        // Format the 'srcset' and 'sizes' string and escape attributes.
    1576         $attr .= sprintf( ' srcset="%s"', esc_attr( $srcset ) );
     1585        $attr = sprintf( ' srcset="%s"', esc_attr( $srcset ) );
    15771586
    15781587        if ( is_string( $sizes ) ) {
    15791588            $attr .= sprintf( ' sizes="%s"', esc_attr( $sizes ) );
    15801589        }
    1581     }
    1582 
    1583     if ( empty( $attr ) ) {
    1584         return $image;
    1585     }
    1586 
    1587     // Add extra attributes to the image markup.
    1588     return preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );
     1590
     1591        // Add extra attributes to the image markup.
     1592        return preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );
     1593    }
     1594
     1595    return $image;
    15891596}
    15901597
     
    16221629 * @since 5.5.0
    16231630 *
     1631 * @see wp_img_tag_add_width_and_height_attr()
     1632 * @see wp_img_tag_add_srcset_and_sizes_attr()
    16241633 * @see wp_img_tag_add_loading_attr()
    1625  * @see wp_img_tag_add_srcset_and_sizes_attr()
    16261634 *
    16271635 * @param string $content The HTML content to be filtered.
     
    16771685        $filtered_image = $image;
    16781686
     1687        // Add 'width' and 'height' attributes if applicable.
     1688        if ( $attachment_id > 0 && false === strpos( $filtered_image, ' width=' ) && false === strpos( $filtered_image, ' height=' ) ) {
     1689            $filtered_image = wp_img_tag_add_width_and_height_attr( $filtered_image, $context, $attachment_id );
     1690        }
     1691
    16791692        // Add 'srcset' and 'sizes' attributes if applicable.
    16801693        if ( $attachment_id > 0 && false === strpos( $filtered_image, ' srcset=' ) ) {
     
    17241737        }
    17251738
    1726         // Images should have dimension attributes for the `loading` attribute to be added.
    1727         if ( false === strpos( $image, ' width=' ) || false === strpos( $image, ' height=' ) ) {
     1739        // Images should have source and dimension attributes for the `loading` attribute to be added.
     1740        if ( false === strpos( $image, ' src=' ) || false === strpos( $image, ' width=' ) || false === strpos( $image, ' height=' ) ) {
    17281741            return $image;
    17291742        }
    17301743
    1731         $quote = null;
    1732 
    1733         // Check if the img tag is valid (has `src` attribute) and get the quote character.
    1734         // In almost all cases it will have src and a double quote.
    1735         if ( false !== strpos( $image, ' src="' ) ) {
    1736             $quote = '"';
    1737         } elseif ( preg_match( '/\ssrc\s*=(["\'])/', $image, $matches ) ) {
    1738             $quote = $matches[1];
    1739         }
    1740 
    1741         if ( $quote ) {
    1742             $loading = "loading={$quote}{$value}{$quote}";
    1743 
    1744             return str_replace( '<img', "<img {$loading}", $image );
     1744        return str_replace( '<img', '<img loading="' . esc_attr( $value ) . '"', $image );
     1745    }
     1746
     1747    return $image;
     1748}
     1749
     1750/**
     1751 * Adds `width` and `height` attributes to an `img` HTML tag.
     1752 *
     1753 * @since 5.5.0
     1754 *
     1755 * @param string $image         The HTML `img` tag where the attribute should be added.
     1756 * @param string $context       Additional context to pass to the filters.
     1757 * @param int    $attachment_id Image attachment ID.
     1758 * @return string Converted 'img' element with 'width' and 'height' attributes added.
     1759 */
     1760function wp_img_tag_add_width_and_height_attr( $image, $context, $attachment_id ) {
     1761    $image_src         = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : '';
     1762    list( $image_src ) = explode( '?', $image_src );
     1763
     1764    // Return early if we couldn't get the image source.
     1765    if ( ! $image_src ) {
     1766        return $image;
     1767    }
     1768
     1769    /**
     1770     * Filters whether to add the missing `width` and `height` HTML attributes to the img tag. Default `true`.
     1771     *
     1772     * Returning anything else than `true` will not add the attributes.
     1773     *
     1774     * @since 5.5.0
     1775     *
     1776     * @param bool   $value         The filtered value, defaults to `true`.
     1777     * @param string $image         The HTML `img` tag where the attribute should be added.
     1778     * @param string $context       Additional context about how the function was called or where the img tag is.
     1779     * @param int    $attachment_id The image attachment ID.
     1780     */
     1781    $add = apply_filters( 'wp_img_tag_add_width_and_height_attr', true, $image, $context, $attachment_id );
     1782
     1783    if ( true === $add ) {
     1784        $image_meta = wp_get_attachment_metadata( $attachment_id );
     1785        $size_array = wp_image_src_get_dimensions( $image_src, $image_meta );
     1786
     1787        if ( $size_array ) {
     1788            $hw = trim( image_hwstring( $size_array[0], $size_array[1] ) );
     1789            return str_replace( '<img', "<img {$hw}", $image );
    17451790        }
    17461791    }
Note: See TracChangeset for help on using the changeset viewer.