Make WordPress Core

Ticket #39941: 39941.4.diff

File 39941.4.diff, 13.4 KB (added by adamsilverstein, 5 years ago)
  • src/wp-includes/functions.php

    diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
    index e6c218d8ad..9ed5408d9a 100644
    a b function is_php_version_compatible( $required ) { 
    78667866function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
    78677867        return abs( (float) $expected - (float) $actual ) <= $precision;
    78687868}
     7869
     7870/**
     7871 * Sanitizes an attributes array into an attributes string to be placed inside a `<script>` tag.
     7872 *
     7873 * Automatically injects type attribute if needed.
     7874 * Used by {@see wp_get_script_tag()} and {@see wp_get_inline_script_tag()}.
     7875 *
     7876 * @since 5.7.0
     7877 *
     7878 * @param array $attributes Key-value pairs representing `<script>` tag attributes.
     7879 * @return string String made of sanitized `<script>` tag attributes.
     7880 */
     7881function wp_sanitize_script_attributes( $attributes ) {
     7882        $html5_script_support = ! is_admin() && ! current_theme_supports( 'html5', 'script' );
     7883        $attributes_string    = '';
     7884
     7885        // If HTML5 script tag is supported, only the attribute name is added
     7886        // to $attributes_string for entries with a boolean value, and that are true.
     7887        foreach ( $attributes as $attribute_name => $attribute_value ) {
     7888                if ( is_bool( $attribute_value ) ) {
     7889                        if ( $attribute_value ) {
     7890                                $attributes_string .= $html5_script_support ? sprintf( ' %1$s="%2$s"', $attribute_name, esc_attr( $attribute_name ) ) : ' ' . $attribute_name;
     7891                        }
     7892                } else {
     7893                        $attributes_string .= sprintf( ' %1$s="%2$s"', $attribute_name, esc_attr( $attribute_value ) );
     7894                }
     7895        }
     7896
     7897        return $attributes_string;
     7898}
     7899
     7900/**
     7901 * Formats `<script>` loader tags.
     7902 *
     7903 * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter.
     7904 * Automatically injects type attribute if needed.
     7905 *
     7906 * @since 5.7.0
     7907 *
     7908 * @param array $attributes Key-value pairs representing `<script>` tag attributes.
     7909 * @return string String containing `<script>` opening and closing tags.
     7910 */
     7911function wp_get_script_tag( $attributes ) {
     7912        if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
     7913                $attributes['type'] = 'text/javascript';
     7914        }
     7915        /**
     7916         * Filters attributes to be added to a script tag.
     7917         *
     7918         * @since 5.7.0
     7919         *
     7920         * @param array $attributes Key-value pairs representing `<script>` tag attributes.
     7921         *                          Only the attribute name is added to the `<script>` tag for
     7922         *                          entries with a boolean value, and that are true.
     7923         */
     7924        $attributes = apply_filters( 'wp_script_attributes', $attributes );
     7925
     7926        return sprintf( "<script%s></script>\n", wp_sanitize_script_attributes( $attributes ) );
     7927}
     7928
     7929/**
     7930 * Prints formatted `<script>` loader tag.
     7931 *
     7932 * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
     7933 * Automatically injects type attribute if needed.
     7934 *
     7935 * @since 5.7.0
     7936 *
     7937 * @param array $attributes Key-value pairs representing `<script>` tag attributes.
     7938 */
     7939function wp_print_script_tag( $attributes ) {
     7940        echo wp_get_script_tag( $attributes );
     7941}
     7942
     7943/**
     7944 * Wraps inline JavaScript in `<script>` tag.
     7945 *
     7946 * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
     7947 * Automatically injects type attribute if needed.
     7948 *
     7949 * @since 5.7.0
     7950 *
     7951 * @param string $javascript Inline JavaScript code.
     7952 * @param array  $attributes  Optional. Key-value pairs representing `<script>` tag attributes.
     7953 * @return string String containing inline JavaScript code wrapped around `<script>` tag.
     7954 */
     7955function wp_get_inline_script_tag( $javascript, $attributes = array() ) {
     7956        if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
     7957                $attributes['type'] = 'text/javascript';
     7958        }
     7959        /**
     7960         * Filters attributes to be added to a script tag.
     7961         *
     7962         * @since 5.7.0
     7963         *
     7964         * @param array $attributes Key-value pairs representing `<script>` tag attributes.
     7965         *                          Only the attribute name is added to the `<script>` tag for
     7966         *                          entries with a boolean value, and that are true.
     7967         */
     7968        $attributes = apply_filters( 'wp_script_attributes', $attributes );
     7969
     7970        $javascript = "\n" . trim( $javascript, "\n\r " ) . "\n";
     7971
     7972        return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $javascript );
     7973}
     7974
     7975/**
     7976 * Prints inline JavaScript wrapped in `<script>` tag.
     7977 *
     7978 * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
     7979 * Automatically injects type attribute if needed.
     7980 *
     7981 * @since 5.7.0
     7982 *
     7983 * @param string $javascript Inline JavaScript code.
     7984 * @param array  $attributes Optional. Key-value pairs representing `<script>` tag attributes.
     7985 */
     7986function wp_print_inline_script_tag( $javascript, $attributes = array() ) {
     7987        echo wp_get_inline_script_tag( $javascript, $attributes );
     7988}
  • new file tests/phpunit/tests/functions/wpInlineScriptTag.php

    diff --git a/tests/phpunit/tests/functions/wpInlineScriptTag.php b/tests/phpunit/tests/functions/wpInlineScriptTag.php
    new file mode 100644
    index 0000000000..d4ece1caa9
    - +  
     1<?php
     2
     3/**
     4 * Test wp_get_inline_script_tag() and wp_print_inline_script_tag().
     5 *
     6 * @group functions.php
     7 */
     8class Tests_Functions_wpInlineScriptTag extends WP_UnitTestCase {
     9
     10        private $event_handler = <<<'JS'
     11document.addEventListener( 'DOMContentLoaded', function () {
     12        document.getElementById( 'elementID' )
     13                        .addEventListener( 'click', function( event ) {
     14                                event.preventDefault();
     15                        });
     16});
     17JS;
     18
     19        public function get_inline_script_tag_type_set() {
     20                add_theme_support( 'html5', array( 'script' ) );
     21
     22                $this->assertSame(
     23                        '<script type="application/javascript" nomodule>' . "\n{$this->event_handler}\n</script>\n",
     24                        wp_get_inline_script_tag(
     25                                $this->event_handler,
     26                                array(
     27                                        'type'     => 'application/javascript',
     28                                        'async'    => false,
     29                                        'nomodule' => true,
     30                                )
     31                        )
     32                );
     33
     34                remove_theme_support( 'html5' );
     35
     36                $this->assertSame(
     37                        '<script type="application/javascript" nomodule>' . "\n{$this->event_handler}\n</script>\n",
     38                        wp_get_inline_script_tag(
     39                                $this->event_handler,
     40                                array(
     41                                        'type'     => 'application/javascript',
     42                                        'async'    => false,
     43                                        'nomodule' => true,
     44                                )
     45                        )
     46                );
     47        }
     48
     49        public function test_get_inline_script_tag_type_not_set() {
     50                add_theme_support( 'html5', array( 'script' ) );
     51
     52                $this->assertSame(
     53                        "<script nomodule>\n{$this->event_handler}\n</script>\n",
     54                        wp_get_inline_script_tag(
     55                                $this->event_handler,
     56                                array(
     57                                        'async'    => false,
     58                                        'nomodule' => true,
     59                                )
     60                        )
     61                );
     62
     63                remove_theme_support( 'html5' );
     64        }
     65
     66        public function test_get_inline_script_tag_unescaped_src() {
     67                add_theme_support( 'html5', array( 'script' ) );
     68
     69                $this->assertSame(
     70                        "<script>\n{$this->event_handler}\n</script>\n",
     71                        wp_get_inline_script_tag( $this->event_handler )
     72                );
     73
     74                remove_theme_support( 'html5' );
     75        }
     76
     77        public function test_print_script_tag_prints_get_inline_script_tag() {
     78                add_filter(
     79                        'wp_script_attributes',
     80                        function ( $attributes ) {
     81                                if ( isset( $attributes['id'] ) && 'utils-js-extra' === $attributes['id'] ) {
     82                                        $attributes['async'] = true;
     83                                }
     84                                return $attributes;
     85                        }
     86                );
     87
     88                add_theme_support( 'html5', array( 'script' ) );
     89
     90                $attributes = array(
     91                        'id'       => 'utils-js-before',
     92                        'nomodule' => true,
     93                );
     94
     95                $this->assertSame(
     96                        wp_get_inline_script_tag( $this->event_handler, $attributes ),
     97                        get_echo(
     98                                'wp_print_inline_script_tag',
     99                                array(
     100                                        $this->event_handler,
     101                                        $attributes,
     102                                )
     103                        )
     104                );
     105
     106                remove_theme_support( 'html5' );
     107
     108                $this->assertSame(
     109                        wp_get_inline_script_tag( $this->event_handler, $attributes ),
     110                        get_echo(
     111                                'wp_print_inline_script_tag',
     112                                array(
     113                                        $this->event_handler,
     114                                        $attributes,
     115                                )
     116                        )
     117                );
     118        }
     119}
  • new file tests/phpunit/tests/functions/wpSanitizeScriptAttributes.php

    diff --git a/tests/phpunit/tests/functions/wpSanitizeScriptAttributes.php b/tests/phpunit/tests/functions/wpSanitizeScriptAttributes.php
    new file mode 100644
    index 0000000000..dd060ebd5d
    - +  
     1<?php
     2
     3/**
     4 * Test wp_sanitize_script_attributes().
     5 *
     6 * @group functions.php
     7 */
     8class Tests_Functions_wpSanitizeScriptAttributes extends WP_UnitTestCase {
     9
     10        function test_sanitize_script_attributes_type_set() {
     11                add_theme_support( 'html5', array( 'script' ) );
     12
     13                $this->assertSame(
     14                        ' type="application/javascript" src="https://DOMAIN.TLD/PATH/FILE.js" nomodule',
     15                        wp_sanitize_script_attributes(
     16                                array(
     17                                        'type'     => 'application/javascript',
     18                                        'src'      => 'https://DOMAIN.TLD/PATH/FILE.js',
     19                                        'async'    => false,
     20                                        'nomodule' => true,
     21                                )
     22                        )
     23                );
     24
     25                remove_theme_support( 'html5' );
     26
     27                $this->assertSame(
     28                        ' src="https://DOMAIN.TLD/PATH/FILE.js" type="application/javascript" nomodule="nomodule"',
     29                        wp_sanitize_script_attributes(
     30                                array(
     31                                        'src'      => 'https://DOMAIN.TLD/PATH/FILE.js',
     32                                        'type'     => 'application/javascript',
     33                                        'async'    => false,
     34                                        'nomodule' => true,
     35                                )
     36                        )
     37                );
     38        }
     39
     40        function test_sanitize_script_attributes_type_not_set() {
     41                add_theme_support( 'html5', array( 'script' ) );
     42
     43                $this->assertSame(
     44                        ' src="https://DOMAIN.TLD/PATH/FILE.js" nomodule',
     45                        wp_sanitize_script_attributes(
     46                                array(
     47                                        'src'      => 'https://DOMAIN.TLD/PATH/FILE.js',
     48                                        'async'    => false,
     49                                        'nomodule' => true,
     50                                )
     51                        )
     52                );
     53
     54                remove_theme_support( 'html5' );
     55
     56                $this->assertSame(
     57                        ' src="https://DOMAIN.TLD/PATH/FILE.js" nomodule="nomodule"',
     58                        wp_sanitize_script_attributes(
     59                                array(
     60                                        'src'      => 'https://DOMAIN.TLD/PATH/FILE.js',
     61                                        'async'    => false,
     62                                        'nomodule' => true,
     63                                )
     64                        )
     65                );
     66        }
     67
     68
     69        function test_sanitize_script_attributes_no_attributes() {
     70                add_theme_support( 'html5', array( 'script' ) );
     71
     72                $this->assertSame(
     73                        '',
     74                        wp_sanitize_script_attributes( array() )
     75                );
     76
     77                remove_theme_support( 'html5' );
     78        }
     79
     80        function test_sanitize_script_attributes_relative_src() {
     81                add_theme_support( 'html5', array( 'script' ) );
     82
     83                $this->assertSame(
     84                        ' src="PATH/FILE.js" nomodule',
     85                        wp_sanitize_script_attributes(
     86                                array(
     87                                        'src'      => 'PATH/FILE.js',
     88                                        'async'    => false,
     89                                        'nomodule' => true,
     90                                )
     91                        )
     92                );
     93
     94                remove_theme_support( 'html5' );
     95        }
     96
     97
     98        function test_sanitize_script_attributes_only_false_boolean_attributes() {
     99                add_theme_support( 'html5', array( 'script' ) );
     100
     101                $this->assertSame(
     102                        '',
     103                        wp_sanitize_script_attributes(
     104                                array(
     105                                        'async'    => false,
     106                                        'nomodule' => false,
     107                                )
     108                        )
     109                );
     110
     111                remove_theme_support( 'html5' );
     112        }
     113
     114        function test_sanitize_script_attributes_only_true_boolean_attributes() {
     115                add_theme_support( 'html5', array( 'script' ) );
     116
     117                $this->assertSame(
     118                        ' async nomodule',
     119                        wp_sanitize_script_attributes(
     120                                array(
     121                                        'async'    => true,
     122                                        'nomodule' => true,
     123                                )
     124                        )
     125                );
     126
     127                remove_theme_support( 'html5' );
     128        }
     129
     130}
  • new file tests/phpunit/tests/functions/wpScriptTag.php

    diff --git a/tests/phpunit/tests/functions/wpScriptTag.php b/tests/phpunit/tests/functions/wpScriptTag.php
    new file mode 100644
    index 0000000000..3c451f5359
    - +  
     1<?php
     2
     3/**
     4 * Test wp_get_script_tag() and wp_print_script_tag().
     5 *
     6 * @group functions.php
     7 */
     8class Tests_Functions_wpScriptTag extends WP_UnitTestCase {
     9
     10        function get_script_tag_type_set() {
     11                add_theme_support( 'html5', array( 'script' ) );
     12
     13                $this->assertSame(
     14                        '<script src="https://localhost/PATH/FILE.js" type="application/javascript" nomodule></script>' . "\n",
     15                        wp_get_script_tag(
     16                                array(
     17                                        'type'     => 'application/javascript',
     18                                        'src'      => 'https://localhost/PATH/FILE.js',
     19                                        'async'    => false,
     20                                        'nomodule' => true,
     21                                )
     22                        )
     23                );
     24
     25                remove_theme_support( 'html5' );
     26
     27                $this->assertSame(
     28                        '<script src="https://localhost/PATH/FILE.js" type="application/javascript" nomodule></script>' . "\n",
     29                        wp_get_script_tag(
     30                                array(
     31                                        'src'      => 'https://localhost/PATH/FILE.js',
     32                                        'type'     => 'application/javascript',
     33                                        'async'    => false,
     34                                        'nomodule' => true,
     35                                )
     36                        )
     37                );
     38        }
     39
     40        function test_get_script_tag_type_not_set() {
     41                add_theme_support( 'html5', array( 'script' ) );
     42
     43                $this->assertSame(
     44                        '<script src="https://localhost/PATH/FILE.js" nomodule></script>' . "\n",
     45                        wp_get_script_tag(
     46                                array(
     47                                        'src'      => 'https://localhost/PATH/FILE.js',
     48                                        'async'    => false,
     49                                        'nomodule' => true,
     50                                )
     51                        )
     52                );
     53
     54                remove_theme_support( 'html5' );
     55        }
     56
     57        function test_print_script_tag_prints_get_script_tag() {
     58                add_filter(
     59                        'wp_script_attributes',
     60                        function ( $attributes ) {
     61                                if ( isset( $attributes['id'] ) && 'utils-js-extra' === $attributes['id'] ) {
     62                                        $attributes['async'] = true;
     63                                }
     64                                return $attributes;
     65                        }
     66                );
     67
     68                add_theme_support( 'html5', array( 'script' ) );
     69
     70                $attributes = array(
     71                        'src'      => 'https://localhost/PATH/FILE.js',
     72                        'id'       => 'utils-js-extra',
     73                        'nomodule' => true,
     74                );
     75
     76                $this->assertSame(
     77                        wp_get_script_tag( $attributes ),
     78                        get_echo(
     79                                'wp_print_script_tag',
     80                                array( $attributes )
     81                        )
     82                );
     83
     84                remove_theme_support( 'html5' );
     85
     86                $this->assertSame(
     87                        wp_get_script_tag( $attributes ),
     88                        get_echo(
     89                                'wp_print_script_tag',
     90                                array( $attributes )
     91                        )
     92                );
     93        }
     94}