From 8a7bcdf6dc0acf39e214f7d616e2c99e6904fb88 Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Wed, 8 Apr 2026 19:37:07 +0200 Subject: [PATCH 1/6] Disable pings/trackbacks in non-production environments --- src/wp-includes/comment.php | 83 ++++++ src/wp-includes/default-filters.php | 6 + .../comment/disablePingsForEnvironment.php | 260 ++++++++++++++++++ tests/phpunit/tests/comment/pingsOpen.php | 7 + 4 files changed, 356 insertions(+) create mode 100644 tests/phpunit/tests/comment/disablePingsForEnvironment.php diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 5395997ecd0ef..4e6c96508e4d1 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3163,6 +3163,89 @@ function generic_ping( $post_id = 0 ) { return $post_id; } +/** + * Determines whether pings should be disabled for the current environment. + * + * By default, all pings (outgoing pingbacks, trackbacks, and ping service + * notifications, as well as incoming pingbacks and trackbacks) are disabled + * for non-production environments ('local', 'development', 'staging'). + * + * @since 6.9.0 + * + * @return bool True if pings should be disabled, false otherwise. + */ +function wp_should_disable_pings_for_environment() { + $environment_type = wp_get_environment_type(); + $should_disable = 'production' !== $environment_type; + + /** + * Filters whether pings should be disabled for the current environment. + * + * Returning false re-enables pings in non-production environments. + * Returning true disables pings even in production. + * + * @since 6.9.0 + * + * @param bool $should_disable Whether pings should be disabled. Default true + * for non-production environments, false for production. + * @param string $environment_type The current environment type as returned by + * wp_get_environment_type(). + */ + return apply_filters( 'wp_should_disable_pings_for_environment', $should_disable, $environment_type ); +} + +/** + * Removes outgoing ping callbacks in non-production environments. + * + * Hooked to `do_all_pings` at priority 1 so it runs before the default + * priority 10 callbacks. Does not remove `do_all_enclosures`. + * + * @since 6.9.0 + * @access private + */ +function wp_disable_outgoing_pings_for_environment() { + if ( wp_should_disable_pings_for_environment() ) { + remove_action( 'do_all_pings', 'do_all_pingbacks', 10 ); + remove_action( 'do_all_pings', 'do_all_trackbacks', 10 ); + remove_action( 'do_all_pings', 'generic_ping', 10 ); + } +} + +/** + * Closes pings for posts in non-production environments. + * + * @since 6.9.0 + * @access private + * + * @param bool $pings_open Whether the post is open for pings. + * @param int $post_id The post ID. + * @return bool False if pings are disabled for the environment, otherwise the original value. + */ +function wp_disable_pings_open_for_environment( $pings_open, $post_id ) { + if ( wp_should_disable_pings_for_environment() ) { + return false; + } + + return $pings_open; +} + +/** + * Removes the pingback XML-RPC method in non-production environments. + * + * @since 6.9.0 + * @access private + * + * @param array $methods Associative array of XML-RPC methods. + * @return array Modified associative array of XML-RPC methods. + */ +function wp_disable_xmlrpc_pingback_for_environment( $methods ) { + if ( wp_should_disable_pings_for_environment() ) { + unset( $methods['pingback.ping'] ); + } + + return $methods; +} + /** * Pings back the links found in a post. * diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 4b6d9de25fa11..bb4a55a8c6395 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -421,6 +421,12 @@ add_action( 'do_all_pings', 'do_all_enclosures', 10, 0 ); add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 ); add_action( 'do_all_pings', 'generic_ping', 10, 0 ); + +// Disable pings (pingbacks, trackbacks, and ping service notifications) in non-production environments. +add_action( 'do_all_pings', 'wp_disable_outgoing_pings_for_environment', 1, 0 ); +add_filter( 'pings_open', 'wp_disable_pings_open_for_environment', 10, 2 ); +add_filter( 'xmlrpc_methods', 'wp_disable_xmlrpc_pingback_for_environment' ); + add_action( 'do_robots', 'do_robots' ); add_action( 'do_favicon', 'do_favicon' ); add_action( 'wp_before_include_template', 'wp_start_template_enhancement_output_buffer', 1000 ); // Late priority to let `wp_template_enhancement_output_buffer` filters and `wp_finalized_template_enhancement_output_buffer` actions be registered. diff --git a/tests/phpunit/tests/comment/disablePingsForEnvironment.php b/tests/phpunit/tests/comment/disablePingsForEnvironment.php new file mode 100644 index 0000000000000..906bb2e5c776f --- /dev/null +++ b/tests/phpunit/tests/comment/disablePingsForEnvironment.php @@ -0,0 +1,260 @@ +original_env = getenv( 'WP_ENVIRONMENT_TYPE' ); + } + + public function tear_down() { + if ( false === $this->original_env ) { + putenv( 'WP_ENVIRONMENT_TYPE' ); + } else { + putenv( 'WP_ENVIRONMENT_TYPE=' . $this->original_env ); + } + parent::tear_down(); + } + + /** + * @ticket 64837 + */ + public function test_should_disable_returns_true_for_local() { + putenv( 'WP_ENVIRONMENT_TYPE=local' ); + $this->assertTrue( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_should_disable_returns_true_for_development() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + $this->assertTrue( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_should_disable_returns_true_for_staging() { + putenv( 'WP_ENVIRONMENT_TYPE=staging' ); + $this->assertTrue( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_should_disable_returns_false_for_production() { + putenv( 'WP_ENVIRONMENT_TYPE=production' ); + $this->assertFalse( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_filter_can_enable_pings_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=local' ); + add_filter( 'wp_should_disable_pings_for_environment', '__return_false' ); + + $this->assertFalse( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_filter_can_disable_pings_in_production() { + putenv( 'WP_ENVIRONMENT_TYPE=production' ); + add_filter( 'wp_should_disable_pings_for_environment', '__return_true' ); + + $this->assertTrue( wp_should_disable_pings_for_environment() ); + } + + /** + * @ticket 64837 + */ + public function test_filter_receives_environment_type() { + putenv( 'WP_ENVIRONMENT_TYPE=staging' ); + + $received_type = null; + add_filter( + 'wp_should_disable_pings_for_environment', + function ( $should_disable, $environment_type ) use ( &$received_type ) { + $received_type = $environment_type; + return $should_disable; + }, + 10, + 2 + ); + + wp_should_disable_pings_for_environment(); + + $this->assertSame( 'staging', $received_type ); + } + + /** + * @ticket 64837 + */ + public function test_outgoing_pingbacks_removed_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + // Re-register the defaults to ensure a clean state. + add_action( 'do_all_pings', 'do_all_pingbacks', 10, 0 ); + + // Fire the priority-1 callback. + wp_disable_outgoing_pings_for_environment(); + + $this->assertFalse( has_action( 'do_all_pings', 'do_all_pingbacks' ) ); + } + + /** + * @ticket 64837 + */ + public function test_outgoing_trackbacks_removed_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 ); + + wp_disable_outgoing_pings_for_environment(); + + $this->assertFalse( has_action( 'do_all_pings', 'do_all_trackbacks' ) ); + } + + /** + * @ticket 64837 + */ + public function test_outgoing_generic_ping_removed_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + add_action( 'do_all_pings', 'generic_ping', 10, 0 ); + + wp_disable_outgoing_pings_for_environment(); + + $this->assertFalse( has_action( 'do_all_pings', 'generic_ping' ) ); + } + + /** + * @ticket 64837 + */ + public function test_enclosures_not_removed_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + add_action( 'do_all_pings', 'do_all_enclosures', 10, 0 ); + + wp_disable_outgoing_pings_for_environment(); + + $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_enclosures' ) ); + } + + /** + * @ticket 64837 + */ + public function test_outgoing_pings_preserved_in_production() { + putenv( 'WP_ENVIRONMENT_TYPE=production' ); + + add_action( 'do_all_pings', 'do_all_pingbacks', 10, 0 ); + add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 ); + add_action( 'do_all_pings', 'generic_ping', 10, 0 ); + + wp_disable_outgoing_pings_for_environment(); + + $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_pingbacks' ) ); + $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_trackbacks' ) ); + $this->assertSame( 10, has_action( 'do_all_pings', 'generic_ping' ) ); + } + + /** + * @ticket 64837 + */ + public function test_pings_open_returns_false_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=local' ); + + $post = self::factory()->post->create_and_get( + array( 'ping_status' => 'open' ) + ); + + $this->assertFalse( wp_disable_pings_open_for_environment( true, $post->ID ) ); + } + + /** + * @ticket 64837 + */ + public function test_pings_open_unchanged_in_production() { + putenv( 'WP_ENVIRONMENT_TYPE=production' ); + + $post = self::factory()->post->create_and_get( + array( 'ping_status' => 'open' ) + ); + + $this->assertTrue( wp_disable_pings_open_for_environment( true, $post->ID ) ); + } + + /** + * @ticket 64837 + */ + public function test_xmlrpc_pingback_removed_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + $methods = array( + 'pingback.ping' => 'this:pingback_ping', + 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', + 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', + ); + + $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + + $this->assertArrayNotHasKey( 'pingback.ping', $filtered ); + } + + /** + * @ticket 64837 + */ + public function test_xmlrpc_pingback_preserved_in_production() { + putenv( 'WP_ENVIRONMENT_TYPE=production' ); + + $methods = array( + 'pingback.ping' => 'this:pingback_ping', + 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', + ); + + $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + + $this->assertArrayHasKey( 'pingback.ping', $filtered ); + } + + /** + * @ticket 64837 + */ + public function test_xmlrpc_other_methods_preserved_in_non_production() { + putenv( 'WP_ENVIRONMENT_TYPE=development' ); + + $methods = array( + 'pingback.ping' => 'this:pingback_ping', + 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks', + 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', + 'wp.getPost' => 'this:wp_getPost', + ); + + $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + + $this->assertArrayHasKey( 'pingback.extensions.getPingbacks', $filtered ); + $this->assertArrayHasKey( 'wp.getUsersBlogs', $filtered ); + $this->assertArrayHasKey( 'wp.getPost', $filtered ); + } +} diff --git a/tests/phpunit/tests/comment/pingsOpen.php b/tests/phpunit/tests/comment/pingsOpen.php index 638f71f1b48d4..0650ccd63c22d 100644 --- a/tests/phpunit/tests/comment/pingsOpen.php +++ b/tests/phpunit/tests/comment/pingsOpen.php @@ -6,6 +6,13 @@ */ class Tests_Comment_PingsOpen extends WP_UnitTestCase { + public function set_up() { + parent::set_up(); + + // Remove the environment-based filter to test core pings_open() behavior in isolation. + remove_filter( 'pings_open', 'wp_disable_pings_open_for_environment' ); + } + /** * @ticket 54159 */ From 44bf1dd8d1f0604fca19cc329a3faa4ac37cc518 Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Wed, 8 Apr 2026 20:04:18 +0200 Subject: [PATCH 2/6] Fix sendHeaders test for environment-based pings filter --- tests/phpunit/tests/wp/sendHeaders.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/phpunit/tests/wp/sendHeaders.php b/tests/phpunit/tests/wp/sendHeaders.php index 4974d74caf8fc..22da8772a1235 100644 --- a/tests/phpunit/tests/wp/sendHeaders.php +++ b/tests/phpunit/tests/wp/sendHeaders.php @@ -8,6 +8,13 @@ class Tests_WP_SendHeaders extends WP_UnitTestCase { protected $headers_sent = array(); + public function set_up() { + parent::set_up(); + + // Remove the environment-based filter to test core behavior in isolation. + remove_filter( 'pings_open', 'wp_disable_pings_open_for_environment' ); + } + /** * @ticket 56068 */ From d048fbac566f9b5d40db86dbadf259967ae06613 Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Wed, 8 Apr 2026 20:19:04 +0200 Subject: [PATCH 3/6] Replace pings_open filter with pre_trackback_post hook The global pings_open filter suppressed the X-Pingback header which wp_install_maybe_enable_pretty_permalinks() uses to verify rewrite rules, breaking pretty permalinks on fresh non-production installs. Use pre_trackback_post action to reject incoming trackbacks instead, which only affects the wp-trackback.php entry point. Reverts the pingsOpen and sendHeaders test changes since pings_open is no longer filtered. --- src/wp-includes/comment.php | 18 ++++++++++-------- src/wp-includes/default-filters.php | 2 +- .../comment/disablePingsForEnvironment.php | 18 ++++++------------ tests/phpunit/tests/comment/pingsOpen.php | 7 ------- tests/phpunit/tests/wp/sendHeaders.php | 7 ------- 5 files changed, 17 insertions(+), 35 deletions(-) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 4e6c96508e4d1..d321be785c8d4 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3212,21 +3212,23 @@ function wp_disable_outgoing_pings_for_environment() { } /** - * Closes pings for posts in non-production environments. + * Rejects incoming trackbacks in non-production environments. + * + * Hooked to `pre_trackback_post` which fires before the trackback is processed. + * Sends an error response and exits if pings are disabled for the environment. * * @since 6.9.0 * @access private * - * @param bool $pings_open Whether the post is open for pings. - * @param int $post_id The post ID. - * @return bool False if pings are disabled for the environment, otherwise the original value. + * @param int $post_id Post ID related to the trackback. + * @param string $trackback_url Trackback URL. */ -function wp_disable_pings_open_for_environment( $pings_open, $post_id ) { +function wp_disable_trackback_for_environment( $post_id, $trackback_url ) { if ( wp_should_disable_pings_for_environment() ) { - return false; + if ( function_exists( 'trackback_response' ) ) { + trackback_response( 1, __( 'Sorry, trackbacks are closed for this item.' ) ); + } } - - return $pings_open; } /** diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index bb4a55a8c6395..4a68432c460a6 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -424,7 +424,7 @@ // Disable pings (pingbacks, trackbacks, and ping service notifications) in non-production environments. add_action( 'do_all_pings', 'wp_disable_outgoing_pings_for_environment', 1, 0 ); -add_filter( 'pings_open', 'wp_disable_pings_open_for_environment', 10, 2 ); +add_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment', 10, 2 ); add_filter( 'xmlrpc_methods', 'wp_disable_xmlrpc_pingback_for_environment' ); add_action( 'do_robots', 'do_robots' ); diff --git a/tests/phpunit/tests/comment/disablePingsForEnvironment.php b/tests/phpunit/tests/comment/disablePingsForEnvironment.php index 906bb2e5c776f..d167aec4dc967 100644 --- a/tests/phpunit/tests/comment/disablePingsForEnvironment.php +++ b/tests/phpunit/tests/comment/disablePingsForEnvironment.php @@ -6,7 +6,7 @@ * @group comment * @covers ::wp_should_disable_pings_for_environment * @covers ::wp_disable_outgoing_pings_for_environment - * @covers ::wp_disable_pings_open_for_environment + * @covers ::wp_disable_trackback_for_environment * @covers ::wp_disable_xmlrpc_pingback_for_environment * * @ticket 64837 @@ -182,27 +182,21 @@ public function test_outgoing_pings_preserved_in_production() { /** * @ticket 64837 */ - public function test_pings_open_returns_false_in_non_production() { - putenv( 'WP_ENVIRONMENT_TYPE=local' ); - - $post = self::factory()->post->create_and_get( - array( 'ping_status' => 'open' ) - ); - - $this->assertFalse( wp_disable_pings_open_for_environment( true, $post->ID ) ); + public function test_trackback_hook_registered_in_non_production() { + $this->assertSame( 10, has_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment' ) ); } /** * @ticket 64837 */ - public function test_pings_open_unchanged_in_production() { - putenv( 'WP_ENVIRONMENT_TYPE=production' ); + public function test_pings_open_unaffected_by_environment() { + putenv( 'WP_ENVIRONMENT_TYPE=local' ); $post = self::factory()->post->create_and_get( array( 'ping_status' => 'open' ) ); - $this->assertTrue( wp_disable_pings_open_for_environment( true, $post->ID ) ); + $this->assertTrue( pings_open( $post ) ); } /** diff --git a/tests/phpunit/tests/comment/pingsOpen.php b/tests/phpunit/tests/comment/pingsOpen.php index 0650ccd63c22d..638f71f1b48d4 100644 --- a/tests/phpunit/tests/comment/pingsOpen.php +++ b/tests/phpunit/tests/comment/pingsOpen.php @@ -6,13 +6,6 @@ */ class Tests_Comment_PingsOpen extends WP_UnitTestCase { - public function set_up() { - parent::set_up(); - - // Remove the environment-based filter to test core pings_open() behavior in isolation. - remove_filter( 'pings_open', 'wp_disable_pings_open_for_environment' ); - } - /** * @ticket 54159 */ diff --git a/tests/phpunit/tests/wp/sendHeaders.php b/tests/phpunit/tests/wp/sendHeaders.php index 22da8772a1235..4974d74caf8fc 100644 --- a/tests/phpunit/tests/wp/sendHeaders.php +++ b/tests/phpunit/tests/wp/sendHeaders.php @@ -8,13 +8,6 @@ class Tests_WP_SendHeaders extends WP_UnitTestCase { protected $headers_sent = array(); - public function set_up() { - parent::set_up(); - - // Remove the environment-based filter to test core behavior in isolation. - remove_filter( 'pings_open', 'wp_disable_pings_open_for_environment' ); - } - /** * @ticket 56068 */ From beec383993abbec56288e2c3f030b0a3d3d0473a Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Wed, 8 Apr 2026 20:31:05 +0200 Subject: [PATCH 4/6] Improve docblocks for ping environment functions --- src/wp-includes/comment.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index d321be785c8d4..0d2afb06d109f 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3214,8 +3214,9 @@ function wp_disable_outgoing_pings_for_environment() { /** * Rejects incoming trackbacks in non-production environments. * - * Hooked to `pre_trackback_post` which fires before the trackback is processed. - * Sends an error response and exits if pings are disabled for the environment. + * Hooked to `pre_trackback_post` which fires in `wp-trackback.php` before the + * trackback is processed. Calls `trackback_response()` which sends an XML error + * response and terminates the request. * * @since 6.9.0 * @access private @@ -3225,9 +3226,7 @@ function wp_disable_outgoing_pings_for_environment() { */ function wp_disable_trackback_for_environment( $post_id, $trackback_url ) { if ( wp_should_disable_pings_for_environment() ) { - if ( function_exists( 'trackback_response' ) ) { - trackback_response( 1, __( 'Sorry, trackbacks are closed for this item.' ) ); - } + trackback_response( 1, __( 'Sorry, trackbacks are closed for this item.' ) ); } } @@ -3237,8 +3236,8 @@ function wp_disable_trackback_for_environment( $post_id, $trackback_url ) { * @since 6.9.0 * @access private * - * @param array $methods Associative array of XML-RPC methods. - * @return array Modified associative array of XML-RPC methods. + * @param string[] $methods An array of XML-RPC methods, keyed by their methodName. + * @return string[] Modified array of XML-RPC methods. */ function wp_disable_xmlrpc_pingback_for_environment( $methods ) { if ( wp_should_disable_pings_for_environment() ) { From f5961fc034ab0bf5c93739902c7c946c6d524c57 Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Thu, 9 Apr 2026 18:05:29 +0200 Subject: [PATCH 5/6] Address PR review feedback --- src/wp-includes/comment.php | 17 +++++++---------- src/wp-includes/default-filters.php | 2 +- .../comment/disablePingsForEnvironment.php | 8 ++++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 0d2afb06d109f..49124495f6f60 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3170,7 +3170,7 @@ function generic_ping( $post_id = 0 ) { * notifications, as well as incoming pingbacks and trackbacks) are disabled * for non-production environments ('local', 'development', 'staging'). * - * @since 6.9.0 + * @since 7.1.0 * * @return bool True if pings should be disabled, false otherwise. */ @@ -3184,7 +3184,7 @@ function wp_should_disable_pings_for_environment() { * Returning false re-enables pings in non-production environments. * Returning true disables pings even in production. * - * @since 6.9.0 + * @since 7.1.0 * * @param bool $should_disable Whether pings should be disabled. Default true * for non-production environments, false for production. @@ -3200,7 +3200,7 @@ function wp_should_disable_pings_for_environment() { * Hooked to `do_all_pings` at priority 1 so it runs before the default * priority 10 callbacks. Does not remove `do_all_enclosures`. * - * @since 6.9.0 + * @since 7.1.0 * @access private */ function wp_disable_outgoing_pings_for_environment() { @@ -3218,22 +3218,19 @@ function wp_disable_outgoing_pings_for_environment() { * trackback is processed. Calls `trackback_response()` which sends an XML error * response and terminates the request. * - * @since 6.9.0 + * @since 7.1.0 * @access private - * - * @param int $post_id Post ID related to the trackback. - * @param string $trackback_url Trackback URL. */ -function wp_disable_trackback_for_environment( $post_id, $trackback_url ) { +function wp_disable_trackback_for_environment() { if ( wp_should_disable_pings_for_environment() ) { - trackback_response( 1, __( 'Sorry, trackbacks are closed for this item.' ) ); + trackback_response( 1, __( 'Trackbacks are disabled in non-production environments.' ) ); } } /** * Removes the pingback XML-RPC method in non-production environments. * - * @since 6.9.0 + * @since 7.1.0 * @access private * * @param string[] $methods An array of XML-RPC methods, keyed by their methodName. diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 4a68432c460a6..649484aa8d5aa 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -424,7 +424,7 @@ // Disable pings (pingbacks, trackbacks, and ping service notifications) in non-production environments. add_action( 'do_all_pings', 'wp_disable_outgoing_pings_for_environment', 1, 0 ); -add_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment', 10, 2 ); +add_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment', 10, 0 ); add_filter( 'xmlrpc_methods', 'wp_disable_xmlrpc_pingback_for_environment' ); add_action( 'do_robots', 'do_robots' ); diff --git a/tests/phpunit/tests/comment/disablePingsForEnvironment.php b/tests/phpunit/tests/comment/disablePingsForEnvironment.php index d167aec4dc967..25021837f5cab 100644 --- a/tests/phpunit/tests/comment/disablePingsForEnvironment.php +++ b/tests/phpunit/tests/comment/disablePingsForEnvironment.php @@ -174,15 +174,15 @@ public function test_outgoing_pings_preserved_in_production() { wp_disable_outgoing_pings_for_environment(); - $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_pingbacks' ) ); - $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_trackbacks' ) ); - $this->assertSame( 10, has_action( 'do_all_pings', 'generic_ping' ) ); + $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_pingbacks' ), 'do_all_pingbacks should still be hooked.' ); + $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_trackbacks' ), 'do_all_trackbacks should still be hooked.' ); + $this->assertSame( 10, has_action( 'do_all_pings', 'generic_ping' ), 'generic_ping should still be hooked.' ); } /** * @ticket 64837 */ - public function test_trackback_hook_registered_in_non_production() { + public function test_trackback_hook_is_registered() { $this->assertSame( 10, has_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment' ) ); } From 3ba7f5241af4f646298a272ca2e385db3258afbe Mon Sep 17 00:00:00 2001 From: Tony Arcangelini Date: Thu, 9 Apr 2026 18:19:33 +0200 Subject: [PATCH 6/6] Address second round of PR review feedback --- src/wp-includes/comment.php | 15 ++++----- src/wp-includes/default-filters.php | 6 ++-- .../comment/disablePingsForEnvironment.php | 32 +++++++++---------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/wp-includes/comment.php b/src/wp-includes/comment.php index 49124495f6f60..70d5c03b378f4 100644 --- a/src/wp-includes/comment.php +++ b/src/wp-includes/comment.php @@ -3201,13 +3201,12 @@ function wp_should_disable_pings_for_environment() { * priority 10 callbacks. Does not remove `do_all_enclosures`. * * @since 7.1.0 - * @access private */ -function wp_disable_outgoing_pings_for_environment() { +function wp_maybe_disable_outgoing_pings_for_environment() { if ( wp_should_disable_pings_for_environment() ) { - remove_action( 'do_all_pings', 'do_all_pingbacks', 10 ); - remove_action( 'do_all_pings', 'do_all_trackbacks', 10 ); - remove_action( 'do_all_pings', 'generic_ping', 10 ); + remove_action( 'do_all_pings', 'do_all_pingbacks' ); + remove_action( 'do_all_pings', 'do_all_trackbacks' ); + remove_action( 'do_all_pings', 'generic_ping' ); } } @@ -3219,9 +3218,8 @@ function wp_disable_outgoing_pings_for_environment() { * response and terminates the request. * * @since 7.1.0 - * @access private */ -function wp_disable_trackback_for_environment() { +function wp_maybe_disable_trackback_for_environment() { if ( wp_should_disable_pings_for_environment() ) { trackback_response( 1, __( 'Trackbacks are disabled in non-production environments.' ) ); } @@ -3231,12 +3229,11 @@ function wp_disable_trackback_for_environment() { * Removes the pingback XML-RPC method in non-production environments. * * @since 7.1.0 - * @access private * * @param string[] $methods An array of XML-RPC methods, keyed by their methodName. * @return string[] Modified array of XML-RPC methods. */ -function wp_disable_xmlrpc_pingback_for_environment( $methods ) { +function wp_maybe_disable_xmlrpc_pingback_for_environment( $methods ) { if ( wp_should_disable_pings_for_environment() ) { unset( $methods['pingback.ping'] ); } diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 649484aa8d5aa..8beb3718f52f5 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -423,9 +423,9 @@ add_action( 'do_all_pings', 'generic_ping', 10, 0 ); // Disable pings (pingbacks, trackbacks, and ping service notifications) in non-production environments. -add_action( 'do_all_pings', 'wp_disable_outgoing_pings_for_environment', 1, 0 ); -add_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment', 10, 0 ); -add_filter( 'xmlrpc_methods', 'wp_disable_xmlrpc_pingback_for_environment' ); +add_action( 'do_all_pings', 'wp_maybe_disable_outgoing_pings_for_environment', 1, 0 ); +add_action( 'pre_trackback_post', 'wp_maybe_disable_trackback_for_environment', 10, 0 ); +add_filter( 'xmlrpc_methods', 'wp_maybe_disable_xmlrpc_pingback_for_environment' ); add_action( 'do_robots', 'do_robots' ); add_action( 'do_favicon', 'do_favicon' ); diff --git a/tests/phpunit/tests/comment/disablePingsForEnvironment.php b/tests/phpunit/tests/comment/disablePingsForEnvironment.php index 25021837f5cab..88fbd3e55f434 100644 --- a/tests/phpunit/tests/comment/disablePingsForEnvironment.php +++ b/tests/phpunit/tests/comment/disablePingsForEnvironment.php @@ -5,9 +5,9 @@ * * @group comment * @covers ::wp_should_disable_pings_for_environment - * @covers ::wp_disable_outgoing_pings_for_environment - * @covers ::wp_disable_trackback_for_environment - * @covers ::wp_disable_xmlrpc_pingback_for_environment + * @covers ::wp_maybe_disable_outgoing_pings_for_environment + * @covers ::wp_maybe_disable_trackback_for_environment + * @covers ::wp_maybe_disable_xmlrpc_pingback_for_environment * * @ticket 64837 */ @@ -118,7 +118,7 @@ public function test_outgoing_pingbacks_removed_in_non_production() { add_action( 'do_all_pings', 'do_all_pingbacks', 10, 0 ); // Fire the priority-1 callback. - wp_disable_outgoing_pings_for_environment(); + wp_maybe_disable_outgoing_pings_for_environment(); $this->assertFalse( has_action( 'do_all_pings', 'do_all_pingbacks' ) ); } @@ -131,7 +131,7 @@ public function test_outgoing_trackbacks_removed_in_non_production() { add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 ); - wp_disable_outgoing_pings_for_environment(); + wp_maybe_disable_outgoing_pings_for_environment(); $this->assertFalse( has_action( 'do_all_pings', 'do_all_trackbacks' ) ); } @@ -144,7 +144,7 @@ public function test_outgoing_generic_ping_removed_in_non_production() { add_action( 'do_all_pings', 'generic_ping', 10, 0 ); - wp_disable_outgoing_pings_for_environment(); + wp_maybe_disable_outgoing_pings_for_environment(); $this->assertFalse( has_action( 'do_all_pings', 'generic_ping' ) ); } @@ -157,9 +157,9 @@ public function test_enclosures_not_removed_in_non_production() { add_action( 'do_all_pings', 'do_all_enclosures', 10, 0 ); - wp_disable_outgoing_pings_for_environment(); + wp_maybe_disable_outgoing_pings_for_environment(); - $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_enclosures' ) ); + $this->assertTrue( has_action( 'do_all_pings', 'do_all_enclosures', 10 ) ); } /** @@ -172,18 +172,18 @@ public function test_outgoing_pings_preserved_in_production() { add_action( 'do_all_pings', 'do_all_trackbacks', 10, 0 ); add_action( 'do_all_pings', 'generic_ping', 10, 0 ); - wp_disable_outgoing_pings_for_environment(); + wp_maybe_disable_outgoing_pings_for_environment(); - $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_pingbacks' ), 'do_all_pingbacks should still be hooked.' ); - $this->assertSame( 10, has_action( 'do_all_pings', 'do_all_trackbacks' ), 'do_all_trackbacks should still be hooked.' ); - $this->assertSame( 10, has_action( 'do_all_pings', 'generic_ping' ), 'generic_ping should still be hooked.' ); + $this->assertTrue( has_action( 'do_all_pings', 'do_all_pingbacks', 10 ), 'do_all_pingbacks should still be hooked at priority 10.' ); + $this->assertTrue( has_action( 'do_all_pings', 'do_all_trackbacks', 10 ), 'do_all_trackbacks should still be hooked at priority 10.' ); + $this->assertTrue( has_action( 'do_all_pings', 'generic_ping', 10 ), 'generic_ping should still be hooked at priority 10.' ); } /** * @ticket 64837 */ public function test_trackback_hook_is_registered() { - $this->assertSame( 10, has_action( 'pre_trackback_post', 'wp_disable_trackback_for_environment' ) ); + $this->assertTrue( has_action( 'pre_trackback_post', 'wp_maybe_disable_trackback_for_environment', 10 ) ); } /** @@ -211,7 +211,7 @@ public function test_xmlrpc_pingback_removed_in_non_production() { 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', ); - $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + $filtered = wp_maybe_disable_xmlrpc_pingback_for_environment( $methods ); $this->assertArrayNotHasKey( 'pingback.ping', $filtered ); } @@ -227,7 +227,7 @@ public function test_xmlrpc_pingback_preserved_in_production() { 'wp.getUsersBlogs' => 'this:wp_getUsersBlogs', ); - $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + $filtered = wp_maybe_disable_xmlrpc_pingback_for_environment( $methods ); $this->assertArrayHasKey( 'pingback.ping', $filtered ); } @@ -245,7 +245,7 @@ public function test_xmlrpc_other_methods_preserved_in_non_production() { 'wp.getPost' => 'this:wp_getPost', ); - $filtered = wp_disable_xmlrpc_pingback_for_environment( $methods ); + $filtered = wp_maybe_disable_xmlrpc_pingback_for_environment( $methods ); $this->assertArrayHasKey( 'pingback.extensions.getPingbacks', $filtered ); $this->assertArrayHasKey( 'wp.getUsersBlogs', $filtered );