From 168b9cee09a1bc00fa2f6aef1f327004fb095794 Mon Sep 17 00:00:00 2001 From: Deepak Prajapati Date: Thu, 21 May 2026 13:03:39 +0530 Subject: [PATCH 1/3] Query: Preserve query strings in old slug redirects. --- src/wp-includes/query.php | 7 ++++++ .../phpunit/tests/rewrite/oldSlugRedirect.php | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 592e70e0290a3..2d573e578faa5 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -1104,6 +1104,13 @@ function wp_old_slug_redirect() { $link = user_trailingslashit( trailingslashit( $link ) . 'embed' ); } + $query_string = isset( $_SERVER['QUERY_STRING'] ) ? (string) $_SERVER['QUERY_STRING'] : ''; + + if ( '' !== $query_string ) { + $link .= false === strpos( $link, '?' ) ? '?' : '&'; + $link .= $query_string; + } + /** * Filters the old slug redirect URL. * diff --git a/tests/phpunit/tests/rewrite/oldSlugRedirect.php b/tests/phpunit/tests/rewrite/oldSlugRedirect.php index cf38ba452eabf..79b2f257aa1d4 100644 --- a/tests/phpunit/tests/rewrite/oldSlugRedirect.php +++ b/tests/phpunit/tests/rewrite/oldSlugRedirect.php @@ -34,6 +34,7 @@ public function set_up() { public function tear_down() { $this->old_slug_redirect_url = null; + unset( $_SERVER['QUERY_STRING'] ); parent::tear_down(); } @@ -55,6 +56,29 @@ public function test_old_slug_redirect() { $this->assertSame( $permalink, $this->old_slug_redirect_url ); } + /** + * @ticket 65267 + */ + public function test_old_slug_redirect_preserves_query_string() { + $old_permalink = user_trailingslashit( get_permalink( self::$post_id ) ); + + wp_update_post( + array( + 'ID' => self::$post_id, + 'post_name' => 'bar-baz', + ) + ); + + $permalink = user_trailingslashit( get_permalink( self::$post_id ) ); + $query_string = 'utm_source=flyer&foo=a%2Bb&a=1&a=2'; + + $this->go_to( $old_permalink . '?' . $query_string ); + $_SERVER['QUERY_STRING'] = $query_string; + + wp_old_slug_redirect(); + $this->assertSame( $permalink . '?' . $query_string, $this->old_slug_redirect_url ); + } + /** * @ticket 36723 */ From 94d119abd79c1015288a17ca04938766495c1105 Mon Sep 17 00:00:00 2001 From: Deepak Prajapati Date: Fri, 29 May 2026 10:28:01 +0530 Subject: [PATCH 2/3] Query: Preserve query strings in old slug redirects. --- src/wp-includes/query.php | 10 ++++++- .../phpunit/tests/rewrite/oldSlugRedirect.php | 30 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 2d573e578faa5..bf7af551781cf 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -1107,8 +1107,16 @@ function wp_old_slug_redirect() { $query_string = isset( $_SERVER['QUERY_STRING'] ) ? (string) $_SERVER['QUERY_STRING'] : ''; if ( '' !== $query_string ) { + $fragment = strstr( $link, '#' ); + + if ( false !== $fragment ) { + $link = substr( $link, 0, -strlen( $fragment ) ); + } else { + $fragment = ''; + } + $link .= false === strpos( $link, '?' ) ? '?' : '&'; - $link .= $query_string; + $link .= $query_string . $fragment; } /** diff --git a/tests/phpunit/tests/rewrite/oldSlugRedirect.php b/tests/phpunit/tests/rewrite/oldSlugRedirect.php index 79b2f257aa1d4..a9b6f9183e030 100644 --- a/tests/phpunit/tests/rewrite/oldSlugRedirect.php +++ b/tests/phpunit/tests/rewrite/oldSlugRedirect.php @@ -34,6 +34,7 @@ public function set_up() { public function tear_down() { $this->old_slug_redirect_url = null; + remove_filter( 'post_link', array( $this, 'filter_post_link_with_query_string_and_fragment' ) ); unset( $_SERVER['QUERY_STRING'] ); parent::tear_down(); @@ -79,6 +80,31 @@ public function test_old_slug_redirect_preserves_query_string() { $this->assertSame( $permalink . '?' . $query_string, $this->old_slug_redirect_url ); } + /** + * @ticket 65267 + */ + public function test_old_slug_redirect_preserves_query_string_before_fragment() { + $old_permalink = user_trailingslashit( get_permalink( self::$post_id ) ); + + wp_update_post( + array( + 'ID' => self::$post_id, + 'post_name' => 'bar-baz', + ) + ); + + $permalink = user_trailingslashit( get_permalink( self::$post_id ) ) . '?existing=1'; + $query_string = 'utm_source=flyer'; + + add_filter( 'post_link', array( $this, 'filter_post_link_with_query_string_and_fragment' ) ); + + $this->go_to( $old_permalink . '?' . $query_string ); + $_SERVER['QUERY_STRING'] = $query_string; + + wp_old_slug_redirect(); + $this->assertSame( $permalink . '&' . $query_string . '#campaign-details', $this->old_slug_redirect_url ); + } + /** * @ticket 36723 */ @@ -238,4 +264,8 @@ public function filter_old_slug_redirect_url( $url ) { $this->old_slug_redirect_url = $url; return false; } + + public function filter_post_link_with_query_string_and_fragment( $url ) { + return $url . '?existing=1#campaign-details'; + } } From 0686a2b1b9c88be56a2c374f66e95ce4e6af6f3f Mon Sep 17 00:00:00 2001 From: Deepak Prajapati Date: Fri, 29 May 2026 11:03:20 +0530 Subject: [PATCH 3/3] Tests: Use a closure for the old slug redirect post_link filter. --- tests/phpunit/tests/rewrite/oldSlugRedirect.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/phpunit/tests/rewrite/oldSlugRedirect.php b/tests/phpunit/tests/rewrite/oldSlugRedirect.php index a9b6f9183e030..ddbf6497d032f 100644 --- a/tests/phpunit/tests/rewrite/oldSlugRedirect.php +++ b/tests/phpunit/tests/rewrite/oldSlugRedirect.php @@ -34,7 +34,6 @@ public function set_up() { public function tear_down() { $this->old_slug_redirect_url = null; - remove_filter( 'post_link', array( $this, 'filter_post_link_with_query_string_and_fragment' ) ); unset( $_SERVER['QUERY_STRING'] ); parent::tear_down(); @@ -96,7 +95,12 @@ public function test_old_slug_redirect_preserves_query_string_before_fragment() $permalink = user_trailingslashit( get_permalink( self::$post_id ) ) . '?existing=1'; $query_string = 'utm_source=flyer'; - add_filter( 'post_link', array( $this, 'filter_post_link_with_query_string_and_fragment' ) ); + add_filter( + 'post_link', + static function ( $url ) { + return $url . '?existing=1#campaign-details'; + } + ); $this->go_to( $old_permalink . '?' . $query_string ); $_SERVER['QUERY_STRING'] = $query_string; @@ -264,8 +268,4 @@ public function filter_old_slug_redirect_url( $url ) { $this->old_slug_redirect_url = $url; return false; } - - public function filter_post_link_with_query_string_and_fragment( $url ) { - return $url . '?existing=1#campaign-details'; - } }