Make WordPress Core

Changeset 62560


Ignore:
Timestamp:
06/25/2026 10:26:14 AM (6 weeks ago)
Author:
cbravobernal
Message:

Emoji: Use the admin_print_footer_scripts action for printing the emoji detection script in the admin.

This corrects an oversight in an optimization made to print_emoji_detection_script() which moved the emoji detection script to the wp_print_footer_scripts action. Since this action doesn't fire in the admin, no script was printed. Now in the admin, the script is printed at the admin_print_footer_scripts action. Existing sites that wish to omit emoji can continue to do remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ).

Tests are added covering all four branches of print_emoji_detection_script(): hooking the script onto the appropriate footer action, and printing it directly when that action has already fired, in both the admin and the frontend.

Missing parameter and return types are added to the get_echo() test helper.

Developed in https://github.com/WordPress/wordpress-develop/pull/11931.
Follow-up to r60902.

Reviewed by jonsurrell.
Merges [62410] to the 7.0 branch.

Props westonruter, jonsurrell.
See #64076, #65260.
Fixes #65310.

Location:
branches/7.0
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/7.0

  • branches/7.0/src/wp-includes/formatting.php

    r61855 r62560  
    58995899 * @since 4.2.0
    59005900 */
    5901 function print_emoji_detection_script() {
     5901function print_emoji_detection_script(): void {
    59025902        static $printed = false;
    59035903
     
    59085908        $printed = true;
    59095909
    5910         if ( did_action( 'wp_print_footer_scripts' ) ) {
    5911                 _print_emoji_detection_script();
     5910        if ( is_admin() ) {
     5911                if ( did_action( 'admin_print_footer_scripts' ) ) {
     5912                        _print_emoji_detection_script();
     5913                } else {
     5914                        add_action( 'admin_print_footer_scripts', '_print_emoji_detection_script' );
     5915                }
    59125916        } else {
    5913                 add_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' );
     5917                if ( did_action( 'wp_print_footer_scripts' ) ) {
     5918                        _print_emoji_detection_script();
     5919                } else {
     5920                        add_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' );
     5921                }
    59145922        }
    59155923}
  • branches/7.0/tests/phpunit/includes/utils.php

    r60703 r62560  
    433433}
    434434
    435 function get_echo( $callback, $args = array() ) {
     435/**
     436 * Gets the output buffer for invoking the provided callback.
     437 *
     438 * @param callable $callback Callback.
     439 * @param mixed[]  $args     Arguments.
     440 * @return string Captured output.
     441 */
     442function get_echo( callable $callback, array $args = array() ): string {
    436443        ob_start();
    437444        call_user_func_array( $callback, $args );
    438         return ob_get_clean();
     445        return (string) ob_get_clean();
    439446}
    440447
  • branches/7.0/tests/phpunit/tests/formatting/emoji.php

    r61194 r62560  
    99        private $png_cdn = 'https://s.w.org/images/core/emoji/17.0.2/72x72/';
    1010        private $svg_cdn = 'https://s.w.org/images/core/emoji/17.0.2/svg/';
     11
     12        /**
     13         * Tests that the emoji detection script is hooked onto the front end footer
     14         * when the footer scripts have not yet been printed.
     15         *
     16         * @ticket 64076
     17         * @ticket 65310
     18         *
     19         * @runInSeparateProcess
     20         * @preserveGlobalState disabled
     21         *
     22         * @covers ::print_emoji_detection_script
     23         */
     24        public function test_print_emoji_detection_script_on_front_end(): void {
     25                $this->assertFalse( is_admin(), 'Expected to not be in the admin.' );
     26                $this->assertFalse(
     27                        has_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' ),
     28                        'Expected _print_emoji_detection_script to not yet be hooked onto wp_print_footer_scripts.'
     29                );
     30
     31                print_emoji_detection_script();
     32
     33                $this->assertSame(
     34                        10,
     35                        has_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' ),
     36                        'Expected _print_emoji_detection_script to be hooked onto wp_print_footer_scripts.'
     37                );
     38                $this->assertFalse(
     39                        has_action( 'admin_print_footer_scripts', '_print_emoji_detection_script' ),
     40                        'Expected _print_emoji_detection_script to not be hooked onto admin_print_footer_scripts.'
     41                );
     42        }
     43
     44        /**
     45         * Tests that the emoji detection script is printed directly when the front
     46         * end footer scripts have already been printed.
     47         *
     48         * @ticket 64076
     49         * @ticket 65310
     50         *
     51         * @runInSeparateProcess
     52         * @preserveGlobalState disabled
     53         *
     54         * @covers ::print_emoji_detection_script
     55         */
     56        public function test_print_emoji_detection_script_on_front_end_after_footer_scripts_printed(): void {
     57                // `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present:
     58                self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' );
     59
     60                $this->assertFalse( is_admin(), 'Expected to not be in the admin.' );
     61
     62                // Fire (and discard the output of) the footer scripts action so it counts as already done.
     63                get_echo( 'do_action', array( 'wp_print_footer_scripts' ) );
     64                $this->assertGreaterThanOrEqual(
     65                        1,
     66                        did_action( 'wp_print_footer_scripts' ),
     67                        'Expected the wp_print_footer_scripts action to have fired.'
     68                );
     69
     70                $output = get_echo( 'print_emoji_detection_script' );
     71
     72                $this->assertStringContainsString(
     73                        'wp-emoji-settings',
     74                        $output,
     75                        'Expected the emoji detection script to be printed directly.'
     76                );
     77                $this->assertFalse(
     78                        has_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' ),
     79                        'Expected _print_emoji_detection_script to not be hooked since it was printed directly.'
     80                );
     81
     82                // A subsequent call should short-circuit via the static $printed guard and print nothing.
     83                $output = get_echo( 'print_emoji_detection_script' );
     84                $this->assertSame(
     85                        '',
     86                        $output,
     87                        'Expected nothing to be printed on a subsequent call due to the static $printed guard.'
     88                );
     89        }
     90
     91        /**
     92         * Tests that the emoji detection script is hooked onto the admin footer
     93         * when the footer scripts have not yet been printed.
     94         *
     95         * @ticket 64076
     96         * @ticket 65310
     97         *
     98         * @runInSeparateProcess
     99         * @preserveGlobalState disabled
     100         *
     101         * @covers ::print_emoji_detection_script
     102         */
     103        public function test_print_emoji_detection_script_in_admin(): void {
     104                set_current_screen( 'edit-post' );
     105                $this->assertTrue( is_admin(), 'Expected to be in the admin.' );
     106                $this->assertFalse(
     107                        has_action( 'admin_print_footer_scripts', '_print_emoji_detection_script' ),
     108                        'Expected _print_emoji_detection_script to not yet be hooked onto admin_print_footer_scripts.'
     109                );
     110
     111                print_emoji_detection_script();
     112
     113                $this->assertSame(
     114                        10,
     115                        has_action( 'admin_print_footer_scripts', '_print_emoji_detection_script' ),
     116                        'Expected _print_emoji_detection_script to be hooked onto admin_print_footer_scripts.'
     117                );
     118                $this->assertFalse(
     119                        has_action( 'wp_print_footer_scripts', '_print_emoji_detection_script' ),
     120                        'Expected _print_emoji_detection_script to not be hooked onto wp_print_footer_scripts.'
     121                );
     122        }
     123
     124        /**
     125         * Tests that the emoji detection script is printed directly when the admin
     126         * footer scripts have already been printed.
     127         *
     128         * @ticket 64076
     129         * @ticket 65310
     130         *
     131         * @runInSeparateProcess
     132         * @preserveGlobalState disabled
     133         *
     134         * @covers ::print_emoji_detection_script
     135         */
     136        public function test_print_emoji_detection_script_in_admin_after_footer_scripts_printed(): void {
     137                // `_print_emoji_detection_script()` assumes `wp-includes/js/wp-emoji-loader.js` is present:
     138                self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' );
     139
     140                set_current_screen( 'edit-post' );
     141                $this->assertTrue( is_admin(), 'Expected to be in the admin.' );
     142
     143                // Fire (and discard the output of) the footer scripts action so it counts as already done.
     144                get_echo( 'do_action', array( 'admin_print_footer_scripts' ) );
     145                $this->assertGreaterThanOrEqual(
     146                        1,
     147                        did_action( 'admin_print_footer_scripts' ),
     148                        'Expected the admin_print_footer_scripts action to have fired.'
     149                );
     150
     151                $output = get_echo( 'print_emoji_detection_script' );
     152
     153                $this->assertStringContainsString(
     154                        'wp-emoji-settings',
     155                        $output,
     156                        'Expected the emoji detection script to be printed directly.'
     157                );
     158                $this->assertFalse(
     159                        has_action( 'admin_print_footer_scripts', '_print_emoji_detection_script' ),
     160                        'Expected _print_emoji_detection_script to not be hooked since it was printed directly.'
     161                );
     162
     163                // A subsequent call should short-circuit via the static $printed guard and print nothing.
     164                $output = get_echo( 'print_emoji_detection_script' );
     165                $this->assertSame(
     166                        '',
     167                        $output,
     168                        'Expected nothing to be printed on a subsequent call due to the static $printed guard.'
     169                );
     170        }
    11171
    12172        /**
Note: See TracChangeset for help on using the changeset viewer.