From 48cd5d95bb26d27f86c0a7fd9cf85d49db0ae684 Mon Sep 17 00:00:00 2001 From: stevemoen Date: Wed, 30 Sep 2026 10:29:50 +0200 Subject: [PATCH 1/8] Update class-sv-wc-admin-notice-handler.php --- woocommerce/class-sv-wc-admin-notice-handler.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/woocommerce/class-sv-wc-admin-notice-handler.php b/woocommerce/class-sv-wc-admin-notice-handler.php index a8eca1484..039fb65d2 100644 --- a/woocommerce/class-sv-wc-admin-notice-handler.php +++ b/woocommerce/class-sv-wc-admin-notice-handler.php @@ -311,7 +311,18 @@ function log_dismissed_notice( pluginID, messageID ) { } ) ( jQuery ); Date: Wed, 14 Oct 2026 13:47:57 +0200 Subject: [PATCH 2/8] Add fallback for wp_print_inline_script_tag function Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- woocommerce/class-sv-wc-admin-notice-handler.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/woocommerce/class-sv-wc-admin-notice-handler.php b/woocommerce/class-sv-wc-admin-notice-handler.php index 039fb65d2..9c976f288 100644 --- a/woocommerce/class-sv-wc-admin-notice-handler.php +++ b/woocommerce/class-sv-wc-admin-notice-handler.php @@ -319,7 +319,11 @@ function log_dismissed_notice( pluginID, messageID ) { // state, and wp_add_inline_script() queues the script too late to be printed. // Fall back to a direct script tag so the notice JS always runs. if ( did_action( 'wp_print_footer_scripts' ) ) { - wp_print_inline_script_tag( $js ); + if ( function_exists( 'wp_print_inline_script_tag' ) ) { + wp_print_inline_script_tag( $js ); + } else { + printf( "\n", $js ); + } } else { ScriptHelper::addInlineScript( $plugin_slug . '-admin-notices', $js ); } From 4fe2da95aa48a9330f51b1b986df54fdafdd66bf Mon Sep 17 00:00:00 2001 From: stevemoen Date: Wed, 28 Oct 2026 12:08:58 +0000 Subject: [PATCH 3/8] Updated Tests --- tests/unit/Helpers/ScriptHelperTest.php | 103 ++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/unit/Helpers/ScriptHelperTest.php diff --git a/tests/unit/Helpers/ScriptHelperTest.php b/tests/unit/Helpers/ScriptHelperTest.php new file mode 100644 index 000000000..4dd988f5d --- /dev/null +++ b/tests/unit/Helpers/ScriptHelperTest.php @@ -0,0 +1,103 @@ + true]); + WP_Mock::userFunction('wp_add_inline_script', ['return' => true]); + } + + /** + * @covers ::addInlineScript + */ + public function testNoWarningOnFrontendBeforeFooterScriptsFire() : void + { + WP_Mock::userFunction('is_admin', ['return' => false]); + WP_Mock::userFunction('did_action', [ + 'return' => static function (string $hook) : int { + return 0; // neither hook has fired + }, + ]); + $this->mockScriptFunctions(); + + ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + $this->addToAssertionCount(1); + } + + /** + * @covers ::addInlineScript + */ + public function testWarningOnFrontendAfterFooterScriptsFire() : void + { + WP_Mock::userFunction('is_admin', ['return' => false]); + WP_Mock::userFunction('did_action', [ + 'return' => static function (string $hook) : int { + return $hook === 'wp_print_footer_scripts' ? 1 : 0; + }, + ]); + WP_Mock::userFunction('_doing_it_wrong', ['times' => 1]); + $this->mockScriptFunctions(); + + ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + } + + /** + * In admin, WP 6.9+'s _wp_get_iframed_editor_assets() calls wp_print_footer_scripts() + * on throwaway WP_Scripts instances, bumping its counter before admin_footer fires. + * addInlineScript must not warn when wp_print_footer_scripts has fired but + * admin_print_footer_scripts has not — this is the key regression the fix addresses. + * + * @covers ::addInlineScript + */ + public function testNoWarningInAdminWhenOnlyWpPrintFooterScriptsFired() : void + { + WP_Mock::userFunction('is_admin', ['return' => true]); + WP_Mock::userFunction('did_action', [ + 'return' => static function (string $hook) : int { + // Simulates the WP 6.9+ iframed-assets scenario: wp_print_footer_scripts + // counter is elevated but admin_print_footer_scripts has not fired yet. + return $hook === 'wp_print_footer_scripts' ? 1 : 0; + }, + ]); + $this->mockScriptFunctions(); + + // _doing_it_wrong is intentionally not mocked; any call would fail the test. + ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + $this->addToAssertionCount(1); + } + + /** + * In admin, the warning fires only after admin_print_footer_scripts has run, + * not merely because wp_print_footer_scripts fired (which the iframed-assets + * collector triggers early). + * + * @covers ::addInlineScript + */ + public function testWarningInAdminAfterAdminFooterScriptsFire() : void + { + WP_Mock::userFunction('is_admin', ['return' => true]); + WP_Mock::userFunction('did_action', [ + 'return' => static function (string $hook) : int { + return $hook === 'admin_print_footer_scripts' ? 1 : 0; + }, + ]); + WP_Mock::userFunction('_doing_it_wrong', ['times' => 1]); + $this->mockScriptFunctions(); + + ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + } +} From c11c33b0c3f2eee97a64aabeef50468c6507d73e Mon Sep 17 00:00:00 2001 From: stevemoen Date: Wed, 28 Oct 2026 12:09:38 +0000 Subject: [PATCH 4/8] Code updates to address Ashely's comment --- woocommerce/Helpers/ScriptHelper.php | 10 +++++++++- .../class-sv-wc-admin-notice-handler.php | 17 +---------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/woocommerce/Helpers/ScriptHelper.php b/woocommerce/Helpers/ScriptHelper.php index 2768991ab..9e59fb50a 100644 --- a/woocommerce/Helpers/ScriptHelper.php +++ b/woocommerce/Helpers/ScriptHelper.php @@ -37,7 +37,15 @@ class ScriptHelper */ public static function addInlineScript(string $handle, string $javaScriptString) : bool { - if (did_action('wp_print_footer_scripts')) { + // In admin, wp_print_footer_scripts() is called early by _wp_get_iframed_editor_assets() + // (WP 6.9+) on throwaway WP_Scripts instances before admin_footer fires, so its counter + // is unreliable there. admin_print_footer_scripts only fires in admin-footer.php, after + // admin_footer (where notice JS is queued at priority 20), so it is the correct sentinel. + $tooLate = is_admin() + ? did_action('admin_print_footer_scripts') + : did_action('wp_print_footer_scripts'); + + if ($tooLate) { _doing_it_wrong(__METHOD__, 'Inline scripts should be added before the wp_print_footer_scripts action.', '6.0.1'); } diff --git a/woocommerce/class-sv-wc-admin-notice-handler.php b/woocommerce/class-sv-wc-admin-notice-handler.php index 9c976f288..a8eca1484 100644 --- a/woocommerce/class-sv-wc-admin-notice-handler.php +++ b/woocommerce/class-sv-wc-admin-notice-handler.php @@ -311,22 +311,7 @@ function log_dismissed_notice( pluginID, messageID ) { } ) ( jQuery ); \n%s\n\n", $js ); - } - } else { - ScriptHelper::addInlineScript( $plugin_slug . '-admin-notices', $js ); - } + ScriptHelper::addInlineScript($plugin_slug.'-admin-notices', ob_get_clean()); } From 7b5e6f41431bac052c3df5db9b07cba055ed7e38 Mon Sep 17 00:00:00 2001 From: stevemoen Date: Wed, 28 Oct 2026 12:18:13 +0000 Subject: [PATCH 5/8] Update ScriptHelperTest to correct failing tests --- tests/unit/Helpers/ScriptHelperTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/Helpers/ScriptHelperTest.php b/tests/unit/Helpers/ScriptHelperTest.php index 4dd988f5d..09e265590 100644 --- a/tests/unit/Helpers/ScriptHelperTest.php +++ b/tests/unit/Helpers/ScriptHelperTest.php @@ -53,6 +53,7 @@ public function testWarningOnFrontendAfterFooterScriptsFire() : void $this->mockScriptFunctions(); ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + $this->addToAssertionCount(1); } /** @@ -99,5 +100,6 @@ public function testWarningInAdminAfterAdminFooterScriptsFire() : void $this->mockScriptFunctions(); ScriptHelper::addInlineScript('test-handle', 'console.log(1);'); + $this->addToAssertionCount(1); } } From 9f00b7b33851a184e2a983eb9629566978e2f25a Mon Sep 17 00:00:00 2001 From: Ashley Gibson Date: Fri, 30 Oct 2026 11:14:11 +0000 Subject: [PATCH 6/8] Update namespace --- tests/unit/Helpers/ScriptHelperTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/Helpers/ScriptHelperTest.php b/tests/unit/Helpers/ScriptHelperTest.php index 09e265590..bcea29fcb 100644 --- a/tests/unit/Helpers/ScriptHelperTest.php +++ b/tests/unit/Helpers/ScriptHelperTest.php @@ -1,13 +1,13 @@ Date: Fri, 30 Oct 2026 11:16:50 +0000 Subject: [PATCH 7/8] Customize messaging based on required hook --- woocommerce/Helpers/ScriptHelper.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/woocommerce/Helpers/ScriptHelper.php b/woocommerce/Helpers/ScriptHelper.php index 4681c7a39..0e363db51 100644 --- a/woocommerce/Helpers/ScriptHelper.php +++ b/woocommerce/Helpers/ScriptHelper.php @@ -41,12 +41,11 @@ public static function addInlineScript(string $handle, string $javaScriptString) // (WP 6.9+) on throwaway WP_Scripts instances before admin_footer fires, so its counter // is unreliable there. admin_print_footer_scripts only fires in admin-footer.php, after // admin_footer (where notice JS is queued at priority 20), so it is the correct sentinel. - $tooLate = is_admin() - ? did_action('admin_print_footer_scripts') - : did_action('wp_print_footer_scripts'); + $requiredHook = is_admin() ? 'admin_print_footer_scripts' : 'wp_print_footer_scripts'; + $tooLate = did_action($requiredHook); if ($tooLate) { - _doing_it_wrong(__METHOD__, 'Inline scripts should be added before the wp_print_footer_scripts action.', '6.0.1'); + _doing_it_wrong(__METHOD__, sprintf('Inline scripts should be added before the %s action.', $requiredHook), '6.0.1'); } if (! wp_script_is($handle, 'registered')) { From def88633b1773db01210947907424ba4b099b28d Mon Sep 17 00:00:00 2001 From: Ashley Gibson Date: Fri, 30 Oct 2026 11:18:13 +0000 Subject: [PATCH 8/8] Update changelog --- woocommerce/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/woocommerce/changelog.txt b/woocommerce/changelog.txt index 832828778..5c902b8d0 100644 --- a/woocommerce/changelog.txt +++ b/woocommerce/changelog.txt @@ -7,6 +7,7 @@ 2026.08.19 - version 6.2.4 * Security - Hardened capability checks around the payment token editor's admin functionality * Tweak - Only load admin token editor JS on profile.php and user-edit.php pages +* Fix - Incorrect `_doing_it_wrong` trigger in `ScriptHelper::addInlineScript()` on WP 6.9+ block editor 2026.06.23 - version 6.2.3 * Fix - Address "wp_script_is was called incorrectly" errors when instantiating the `SV_WP_Job_Batch_Handler` class