Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/wp-includes/query.php
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,21 @@ function wp_old_slug_redirect() {
return;
}

wp_redirect( $link, 301 ); // Permanent redirect.
/**
* Filters the old slug redirect status code.
*
* @since 6.9.0
*
* @param int $status The HTTP response status code to use for the redirect.
* @param int $id The post ID being redirected to.
*/
$status = apply_filters( 'old_slug_redirect_status', 301, $id );

if ( ! $status ) {
return;
}

wp_redirect( $link, $status );
exit;
}
}
Expand Down
85 changes: 85 additions & 0 deletions tests/phpunit/tests/rewrite/oldSlugRedirect.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
*/
class Tests_Rewrite_OldSlugRedirect extends WP_UnitTestCase {
protected $old_slug_redirect_url;
protected $redirect_status;
protected $redirect_location;
protected $redirect_post_id;

protected static $post_id;

Expand Down Expand Up @@ -34,6 +37,9 @@ public function set_up() {

public function tear_down() {
$this->old_slug_redirect_url = null;
$this->redirect_status = null;
$this->redirect_location = null;
$this->redirect_post_id = null;

parent::tear_down();
}
Expand Down Expand Up @@ -214,4 +220,83 @@ public function filter_old_slug_redirect_url( $url ) {
$this->old_slug_redirect_url = $url;
return false;
}

/**
* Test that the old_slug_redirect_status filter works correctly.
*
* @ticket 52737
*/
public function test_old_slug_redirect_status_filter() {
// Use the same pattern as the working test
$old_permalink = user_trailingslashit( get_permalink( self::$post_id ) );

wp_update_post(
array(
'ID' => self::$post_id,
'post_name' => 'status-filter-test',
)
);

// Remove the default URL filter temporarily to test the redirect status
remove_filter( 'old_slug_redirect_url', array( $this, 'filter_old_slug_redirect_url' ) );

// Test default 301 status.
add_filter( 'wp_redirect', array( $this, 'capture_redirect_status' ), 10, 2 );

$this->go_to( $old_permalink );
wp_old_slug_redirect();

$this->assertSame( 301, $this->redirect_status );
$this->assertSame( self::$post_id, $this->redirect_post_id );

// Reset state for next test
$this->redirect_status = null;
$this->redirect_post_id = null;

// Test custom 302 status.
add_filter( 'old_slug_redirect_status', array( $this, 'filter_redirect_status_to_302' ), 10, 2 );

$this->go_to( $old_permalink );
wp_old_slug_redirect();

$this->assertSame( 302, $this->redirect_status );
$this->assertSame( self::$post_id, $this->redirect_post_id );

// Test that returning 0 prevents redirect.
remove_filter( 'old_slug_redirect_status', array( $this, 'filter_redirect_status_to_302' ) );
add_filter( 'old_slug_redirect_status', array( $this, 'filter_redirect_status_to_zero' ), 10, 2 );

$this->redirect_status = null;
$this->redirect_post_id = null;

$this->go_to( $old_permalink );
wp_old_slug_redirect();

$this->assertNull( $this->redirect_status );
$this->assertNull( $this->redirect_post_id );

// Clean up.
remove_filter( 'wp_redirect', array( $this, 'capture_redirect_status' ) );
remove_filter( 'old_slug_redirect_status', array( $this, 'filter_redirect_status_to_zero' ) );

// Restore the URL filter
add_filter( 'old_slug_redirect_url', array( $this, 'filter_old_slug_redirect_url' ), 10, 1 );
}

public function capture_redirect_status( $location, $status ) {
$this->redirect_status = $status;
$this->redirect_location = $location;
// Prevent actual redirect in tests.
return false;
}

public function filter_redirect_status_to_302( $status, $post_id ) {
$this->redirect_post_id = $post_id;
return 302;
}

public function filter_redirect_status_to_zero( $status, $post_id ) {
$this->redirect_post_id = $post_id;
return 0;
}
}
Loading