WordPress.org

Make WordPress Core

Ticket #30180: 30180.2.1.patch

File 30180.2.1.patch, 17.6 KB (added by ryanshoover, 9 months ago)

Attaching improved version of the patch

  • src/wp-admin/custom-header.php

     
    14611461        public function get_uploaded_header_images() {
    14621462                $header_images = get_uploaded_header_images();
    14631463                $timestamp_key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
    1464                 $alt_text_key  = '_wp_attachment_image_alt';
    14651464
    14661465                foreach ( $header_images as &$header_image ) {
    1467                         $header_meta               = get_post_meta( $header_image['attachment_id'] );
    1468                         $header_image['timestamp'] = isset( $header_meta[ $timestamp_key ] ) ? $header_meta[ $timestamp_key ] : '';
    1469                         $header_image['alt_text']  = isset( $header_meta[ $alt_text_key ] ) ? $header_meta[ $alt_text_key ] : '';
     1466                        $header_image['timestamp'] = get_post_meta( $header_image['attachment_id'], 'timestamp', true );
     1467                        $header_image['alt_text']  = wp_get_attachment_image_attr( $header_image['attachment_id'], 'alt' );
    14701468                }
    14711469
    14721470                return $header_images;
  • src/wp-admin/includes/media.php

     
    13571357
    13581358        // This was formerly in image_attachment_fields_to_edit().
    13591359        if ( substr( $post->post_mime_type, 0, 5 ) == 'image' ) {
    1360                 $alt = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );
     1360                $alt = wp_get_attachment_image_attr( $post->ID, 'alt' );
    13611361                if ( empty( $alt ) ) {
    13621362                        $alt = '';
    13631363                }
  • src/wp-includes/general-template.php

     
    905905                 * If the logo alt attribute is empty, get the site title and explicitly
    906906                 * pass it to the attributes used by wp_get_attachment_image().
    907907                 */
    908                 $image_alt = get_post_meta( $custom_logo_id, '_wp_attachment_image_alt', true );
     908                $image_alt = wp_get_attachment_image_attr( $custom_logo_id, 'alt' );
    909909                if ( empty( $image_alt ) ) {
    910910                        $custom_logo_attr['alt'] = get_bloginfo( 'name', 'display' );
    911911                }
  • src/wp-includes/media.php

     
    854854}
    855855
    856856/**
     857 * Retrieve an image attribute value.
     858 *
     859 * Retrieve either a single image attribute value or all relevant attribute values. The possible
     860 * values are `alt`, `description`, `caption`, `src`, `width`, `height`, `srcset`, `sizes`, `class`. When
     861 * retrieving src, width, height, srcset, sizes, or class, you can specify the size of the image to retrieve
     862 * in the args parameter. Passing in an empty attribute value will return all relevant values.
     863 *
     864 * @since 5.X
     865 *
     866 * @param int          $attachment_id Image attachment ID.
     867 * @param string|array $attribute     Image attribute to retrieve. An empty value or `all` will retrieve all values.
     868 * @param array        $args          Optional. Array of attributes for the function. Currently only
     869 *                                    supports 'size' for the image source.
     870 * @return null|string|array          Returns the value of the attribute or attributes requested. A single
     871 *                                    attribute will return a single value. An array of attributes or no
     872 *                                    attribute will return an array of values.
     873 */
     874function wp_get_attachment_image_attr( $attachment_id, $attribute = array(), $args = array() ) {
     875        $image = get_post( $attachment_id );
     876
     877        // If this isn't an image, bail early with null.
     878        if ( empty( $image ) ) {
     879                return null;
     880        }
     881
     882        $values = array();
     883        $names  = array();
     884
     885        if ( empty( $attribute ) || 'all' === $attribute ) {
     886                // If an empty value is passed for the attr name, return all our attributes.
     887                $names = array(
     888                        'alt',
     889                        'description',
     890                        'caption',
     891                        'src',
     892                        'width',
     893                        'height',
     894                        'srcset',
     895                        'sizes',
     896                        'class',
     897                );
     898        } elseif ( is_string( $attribute ) ) {
     899                // If the attribute name is a string, convert it to an array.
     900                $names = array( $attribute );
     901        }
     902
     903        // Get a valid args array.
     904        $default_args = array(
     905                'icon' => false,
     906                'size' => null,
     907        );
     908
     909        $args = wp_parse_args( $args, $default_args );
     910
     911        // Loop through our names and get the value for each one.
     912        foreach ( $names as $name ) {
     913                switch ( $name ) {
     914                        case 'alt':
     915                                $values[ $name ] = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
     916                                break;
     917
     918                        case 'description':
     919                                $values[ $name ] = $image->post_content;
     920                                break;
     921
     922                        case 'caption':
     923                                $values[ $name ] = $image->post_excerpt;
     924                                break;
     925
     926                        case 'src':
     927                                if ( ! isset( $image_src ) ) {
     928                                        $image_src = wp_get_attachment_image_src( $attachment_id, $args['size'], $args['icon'] );
     929                                }
     930
     931                                $values[ $name ] = $image_src[0];
     932                                break;
     933
     934                        case 'width':
     935                                if ( ! isset( $image_src ) ) {
     936                                        $image_src = wp_get_attachment_image_src( $attachment_id, $args['size'], $args['icon'] );
     937                                }
     938
     939                                $values[ $name ] = $image_src[1];
     940                                break;
     941
     942                        case 'height':
     943                                if ( ! isset( $image_src ) ) {
     944                                        $image_src = wp_get_attachment_image_src( $attachment_id, $args['size'], $args['icon'] );
     945                                }
     946
     947                                $values[ $name ] = $image_src[2];
     948                                break;
     949
     950                        case 'srcset':
     951                                $values[ $name ] = wp_get_attachment_image_srcset( $attachment_id, $args['size'] );
     952                                break;
     953
     954                        case 'sizes':
     955                                $values[ $name ] = wp_get_attachment_image_sizes( $attachment_id, $args['size'] );
     956                                break;
     957
     958                        case 'class':
     959                                $size_class = $args['size'];
     960
     961                                if ( is_array( $size_class ) ) {
     962                                        $size_class = join( 'x', $size_class );
     963                                }
     964
     965                                $values[ $name ] = 'attachment-' . $size_class . ' size-' . $size_class;
     966                                break;
     967                }
     968        }
     969
     970        /**
     971         * Filters the image attr result.
     972         *
     973         * Will apply to all image attribute types.
     974         *
     975         * @since 5.x
     976         *
     977         * @param string|int $values         Value of the attribute.
     978         * @param int        $attachment_id Image attachment ID.
     979         * @param string     $name     Name of the attribute being retrieved.
     980         * @param array      $args          Arguments passed into the function.
     981         */
     982        $values = apply_filters( 'wp_get_attachment_image_attr', $values, $attachment_id, $attribute, $args );
     983
     984        // If we didn't request a single attribute, we're done.
     985        if ( is_array( $attribute ) || empty( $attribute ) || 'all' === $attribute ) {
     986                return $values;
     987        }
     988
     989        if ( ! empty( $values[ $attribute ] ) ) {
     990                $value = $values[ $attribute ];
     991        } else {
     992                $value = null;
     993        }
     994
     995        /**
     996         * Filters the image attr result.
     997         *
     998         * This is a dynamic filter that will generate a distinct filter for each attribute type.
     999         * It only runs if the requested attribute is a string.
     1000         *
     1001         * <code>
     1002         * <?php
     1003         * function filter_alt_text( $alt ) {
     1004         *     $alt = $alt . ' Extra content';
     1005         *     return $alt;
     1006         * }
     1007         * add_filter( 'wp_get_attachment_image_attr_alt', 'filter_alt_text' );
     1008         * </code>
     1009         *
     1010         * @since 5.x
     1011         *
     1012         * @param string|int $value         Value of the attribute.
     1013         * @param int        $attachment_id Image attachment ID.
     1014         * @param array      $args          Arguments passed into the function.
     1015         */
     1016        $value = apply_filters( 'wp_get_attachment_image_attr_' . $attribute, $value, $attachment_id, $args );
     1017
     1018        return $value;
     1019}
     1020
     1021/**
    8571022 * Get an HTML img element representing an image attachment
    8581023 *
    8591024 * While `$size` will accept an array, it is better to register a size with
     
    8711036 * @return string HTML img element or empty string on failure.
    8721037 */
    8731038function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = false, $attr = '' ) {
    874         $html  = '';
    875         $image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
    876         if ( $image ) {
    877                 list($src, $width, $height) = $image;
    878                 $hwstring                   = image_hwstring( $width, $height );
    879                 $size_class                 = $size;
    880                 if ( is_array( $size_class ) ) {
    881                         $size_class = join( 'x', $size_class );
    882                 }
    883                 $attachment   = get_post( $attachment_id );
    884                 $default_attr = array(
    885                         'src'   => $src,
    886                         'class' => "attachment-$size_class size-$size_class",
    887                         'alt'   => trim( strip_tags( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ) ),
    888                 );
     1039        $html = '';
    8891040
    890                 $attr = wp_parse_args( $attr, $default_attr );
     1041        $image_attr_args = array(
     1042                'size' => $size,
     1043                'icon' => $icon,
     1044        );
    8911045
    892                 // Generate 'srcset' and 'sizes' if not already present.
    893                 if ( empty( $attr['srcset'] ) ) {
    894                         $image_meta = wp_get_attachment_metadata( $attachment_id );
     1046        $image_attr = wp_get_attachment_image_attr( $attachment_id, 'all', $image_attr_args );
    8951047
    896                         if ( is_array( $image_meta ) ) {
    897                                 $size_array = array( absint( $width ), absint( $height ) );
    898                                 $srcset     = wp_calculate_image_srcset( $size_array, $src, $image_meta, $attachment_id );
    899                                 $sizes      = wp_calculate_image_sizes( $size_array, $src, $image_meta, $attachment_id );
     1048        // If the image attribute fetch failed, return an empty string.
     1049        if ( empty( $image_attr ) ) {
     1050                return $html;
     1051        }
    9001052
    901                                 if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
    902                                         $attr['srcset'] = $srcset;
     1053        $hwstring     = image_hwstring( $image_attr['width'], $image_attr['height'] );
     1054        $attachment   = get_post( $attachment_id );
     1055        $default_attr = array(
     1056                'src'   => $src,
     1057                'class' => $image_attr['class'],
     1058                'alt'   => trim( strip_tags( $image_attr['alt'] ) ),
     1059        );
    9031060
    904                                         if ( empty( $attr['sizes'] ) ) {
    905                                                 $attr['sizes'] = $sizes;
    906                                         }
    907                                 }
    908                         }
    909                 }
     1061        $attr = wp_parse_args( $attr, $default_attr );
    9101062
    911                 /**
    912                  * Filters the list of attachment image attributes.
    913                  *
    914                  * @since 2.8.0
    915                  *
    916                  * @param array        $attr       Attributes for the image markup.
    917                  * @param WP_Post      $attachment Image attachment post.
    918                  * @param string|array $size       Requested size. Image size or array of width and height values
    919                  *                                 (in that order). Default 'thumbnail'.
    920                  */
    921                 $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
    922                 $attr = array_map( 'esc_attr', $attr );
    923                 $html = rtrim( "<img $hwstring" );
    924                 foreach ( $attr as $name => $value ) {
    925                         $html .= " $name=" . '"' . $value . '"';
     1063        // Generate 'srcset' and 'sizes' if not already present.
     1064        if ( empty( $attr['srcset'] ) &&
     1065                ! empty( $image_attr['srcset'] ) &&
     1066                ( ! empty( $image_attr['sizes'] ) || ! empty( $attr['sizes'] ) ) ) {
     1067
     1068                $attr['srcset'] = $image_attr['srcset'];
     1069
     1070                if ( empty( $attr['sizes'] ) ) {
     1071                        $attr['sizes'] = $image_attr['sizes'];
    9261072                }
    927                 $html .= ' />';
    9281073        }
    9291074
     1075        /**
     1076         * Filters the list of attachment image attributes.
     1077         *
     1078         * @since 2.8.0
     1079         *
     1080         * @param array        $attr       Attributes for the image markup.
     1081         * @param WP_Post      $attachment Image attachment post.
     1082         * @param string|array $size       Requested size. Image size or array of width and height values
     1083         *                                 (in that order). Default 'thumbnail'.
     1084         */
     1085        $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
     1086        $attr = array_map( 'esc_attr', $attr );
     1087        $html = rtrim( "<img $hwstring" );
     1088
     1089        foreach ( $attr as $name => $value ) {
     1090                $html .= ' ' .  $name . '="' . $value . '"';
     1091        }
     1092
     1093        $html .= ' />';
     1094
    9301095        return $html;
    9311096}
    9321097
  • src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php

     
    308308                }
    309309
    310310                if ( in_array( 'alt_text', $fields, true ) ) {
    311                         $data['alt_text'] = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );
     311                        $data['alt_text'] = wp_get_attachment_image_attr( $post->ID, 'alt' );
    312312                }
    313313
    314314                if ( in_array( 'media_type', $fields, true ) ) {
  • src/wp-includes/theme.php

     
    12751275                $header_images[ $header_index ]['attachment_id']     = $header->ID;
    12761276                $header_images[ $header_index ]['url']               = $url;
    12771277                $header_images[ $header_index ]['thumbnail_url']     = $url;
    1278                 $header_images[ $header_index ]['alt_text']          = get_post_meta( $header->ID, '_wp_attachment_image_alt', true );
     1278                $header_images[ $header_index ]['alt_text']          = wp_get_attachment_image_attr( $header->ID, 'alt' );
    12791279                $header_images[ $header_index ]['attachment_parent'] = isset( $header_data['attachment_parent'] ) ? $header_data['attachment_parent'] : '';
    12801280
    12811281                if ( isset( $header_data['width'] ) ) {
  • tests/phpunit/tests/media/getAttachmentAttributes.php

     
     1<?php
     2
     3/**
     4 * @group media
     5 * @group attribute
     6 */
     7class Tests_Media_GetAttachmentAttributes extends WP_UnitTestCase {
     8        public function test_should_return_attachment_attr_alt() {
     9                $alt = 'Alt text';
     10
     11                $a = self::factory()->attachment->create_object(
     12                        array(
     13                                'post_title'     => 'Unit Test Attachment',
     14                                'post_content'   => '',
     15                        )
     16                );
     17
     18                $attachment = get_post( $a );
     19
     20                update_post_meta( $attachment->ID, '_wp_attachment_image_alt', $alt );
     21
     22                $found    = wp_get_attachment_image_attr( $attachment->ID, 'alt' );
     23                $expected = $alt;
     24
     25                $this->assertSame( $expected, $found );
     26        }
     27
     28        public function test_should_return_attachment_attr_caption() {
     29                $caption = 'Image Caption';
     30
     31                $a = self::factory()->attachment->create_object(
     32                        array(
     33                                'post_title'     => 'Unit Test Attachment',
     34                                'post_content'   => '',
     35                                'post_excerpt'   => $caption,
     36                        )
     37                );
     38
     39                $attachment = get_post( $a );
     40
     41                $found    = wp_get_attachment_image_attr( $attachment->ID, 'caption' );
     42                $expected = $caption;
     43
     44                $this->assertSame( $expected, $found );
     45        }
     46
     47        public function test_should_return_attachment_attr_description() {
     48                $description = 'Image Description';
     49
     50                $a = self::factory()->attachment->create_object(
     51                        array(
     52                                'post_title'     => 'Unit Test Attachment',
     53                                'post_content'   => $description,
     54                        )
     55                );
     56
     57                $attachment = get_post( $a );
     58
     59                $found    = wp_get_attachment_image_attr( $attachment->ID, 'description' );
     60                $expected = $description;
     61
     62                $this->assertSame( $expected, $found );
     63        }
     64
     65        public function test_should_return_attachment_attr_class() {
     66                $a = self::factory()->attachment->create_object(
     67                        array(
     68                                'post_title'     => 'Unit Test Attachment',
     69                                'post_content'   => '',
     70                        )
     71                );
     72
     73                $attachment = get_post( $a );
     74
     75                $found = wp_get_attachment_image_attr(
     76                        $attachment->ID,
     77                        'class',
     78                        array( 'size' => 'large' )
     79                );
     80
     81                $expected = 'attachment-large size-large';
     82
     83                $this->assertSame( $expected, $found );
     84        }
     85
     86        public function test_should_return_attachment_attr_src() {
     87                $image = DIR_TESTDATA . '/images/canola.jpg';
     88
     89                $a = self::factory()->attachment->create_upload_object( $image );
     90
     91                $attachment = get_post( $a );
     92
     93                $found = wp_get_attachment_image_attr(
     94                        $attachment->ID,
     95                        'src',
     96                        array( 'size' => 'thumbnail' )
     97                );
     98
     99                $expected = 'http://example.org/wp-content/uploads/';
     100                $expected .= date( 'Y/j/');
     101                $expected .= substr( $attachment->post_name, 0, -4 ) . '-150x150.jpg';
     102
     103                $this->assertSame( $expected, $found );
     104        }
     105
     106        public function test_should_return_attachment_attr_width() {
     107                $image = DIR_TESTDATA . '/images/canola.jpg';
     108
     109                $a = self::factory()->attachment->create_upload_object( $image );
     110
     111                $attachment = get_post( $a );
     112
     113                $found = wp_get_attachment_image_attr(
     114                        $attachment->ID,
     115                        'width',
     116                        array( 'size' => 'large' )
     117                );
     118
     119                $expected = 640;
     120
     121                $this->assertSame( $expected, $found );
     122        }
     123
     124        public function test_should_return_attachment_attr_height() {
     125                $image = DIR_TESTDATA . '/images/canola.jpg';
     126
     127                $a = self::factory()->attachment->create_upload_object( $image );
     128
     129                $attachment = get_post( $a );
     130
     131                $found = wp_get_attachment_image_attr(
     132                        $attachment->ID,
     133                        'height',
     134                        array( 'size' => 'large' )
     135                );
     136
     137                $expected = 480;
     138
     139                $this->assertSame( $expected, $found );
     140        }
     141
     142        public function test_should_return_attachment_attr_srcset() {
     143                $image = DIR_TESTDATA . '/images/canola.jpg';
     144
     145                $a = self::factory()->attachment->create_upload_object( $image );
     146
     147                $attachment = get_post( $a );
     148
     149                $found = wp_get_attachment_image_attr(
     150                        $attachment->ID,
     151                        'srcset',
     152                        array( 'size' => 'large' )
     153                );
     154
     155                $url_large = 'http://example.org/wp-content/uploads/';
     156                $url_large .= date( 'Y/j/');
     157                $url_large .= substr( $attachment->post_name, 0, -4 ) . '.jpg';
     158
     159                $url_small = 'http://example.org/wp-content/uploads/';
     160                $url_small .= date( 'Y/j/');
     161                $url_small .= substr( $attachment->post_name, 0, -4 ) . '-300x225.jpg';
     162
     163                $expected = $url_large . ' 640w, ' . $url_small . ' 300w';
     164
     165                $this->assertSame( $expected, $found );
     166        }
     167
     168        public function test_should_return_attachment_attr_sizes() {
     169                $image = DIR_TESTDATA . '/images/canola.jpg';
     170
     171                $a = self::factory()->attachment->create_upload_object( $image );
     172
     173                $attachment = get_post( $a );
     174
     175                $found = wp_get_attachment_image_attr(
     176                        $attachment->ID,
     177                        'sizes',
     178                        array( 'size' => 'large' )
     179                );
     180
     181                $expected = '(max-width: 640px) 100vw, 640px';
     182
     183                $this->assertSame( $expected, $found );
     184        }
     185}