Skip to content

Commit a3c3968

Browse files
committed
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 WordPress#11931. Follow-up to r60902. Props westonruter, jonsurrell. See #64076, #65260. Fixes #65310. git-svn-id: https://develop.svn.wordpress.org/trunk@62410 602fd350-edb4-49c9-b593-d223f7449a82
1 parent bc730ed commit a3c3968

3 files changed

Lines changed: 181 additions & 6 deletions

File tree

src/wp-includes/formatting.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5898,7 +5898,7 @@ function wp_enqueue_emoji_styles() {
58985898
*
58995899
* @since 4.2.0
59005900
*/
5901-
function print_emoji_detection_script() {
5901+
function print_emoji_detection_script(): void {
59025902
static $printed = false;
59035903

59045904
if ( $printed ) {
@@ -5907,10 +5907,18 @@ function print_emoji_detection_script() {
59075907

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
}
59165924

tests/phpunit/includes/utils.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,17 @@ function dmp_filter( $a ) {
432432
return $a;
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+
*/
442+
function 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

441448
// Recursively generate some quick assertEquals() tests based on an array.

tests/phpunit/tests/formatting/emoji.php

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,166 @@ class Tests_Formatting_Emoji extends WP_UnitTestCase {
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/';
1111

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+
}
171+
12172
/**
13173
* @ticket 63842
14174
*

0 commit comments

Comments
 (0)