diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 7abd4d4d0e..28cf56f74a 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -4725,12 +4725,14 @@ class WP_Query { * * @since 2.1.0 * - * @global WP_Query $wp_query Global WP_Query instance. - * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Query $wp_query Global WP_Query instance. + * @global wpdb $wpdb WordPress database abstraction object. + * @global WP_Rewrite $wp_rewrite WordPress rewrite component. */ function wp_old_slug_redirect() { - global $wp_query; - if ( is_404() && '' != $wp_query->query_vars['name'] ) : + global $wp_query, $wp_rewrite; + + if ( '' !== $wp_query->query_vars['name'] ) : global $wpdb; // Guess the current post_type based on the query vars. @@ -4767,10 +4769,33 @@ function wp_old_slug_redirect() { if ( ! $id ) return; - $link = get_permalink($id); + $link = get_permalink( $id ); - if ( !$link ) + if ( is_feed() ) { + $link = user_trailingslashit( trailingslashit( $link ) . 'feed' ); + } elseif ( isset( $GLOBALS['wp_query']->query_vars['paged'] ) && $GLOBALS['wp_query']->query_vars['paged'] > 1 ) { + $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . $GLOBALS['wp_query']->query_vars['paged'] ); + } elseif ( is_404() ) { + // Add rewrite endpoints if necessary. + foreach ( $wp_rewrite->endpoints as $endpoint ) { + if ( $endpoint[2] && false !== get_query_var( $endpoint[2], false ) ) { + $link = user_trailingslashit( trailingslashit( $link ) . $endpoint[1] ); + } + } + } + + /** + * Filter the old slug redirect URL. + * + * @since 4.4.0 + * + * @param string $link The redirect URL. + */ + $link = apply_filters( 'old_slug_redirect_url', $link ); + + if ( ! $link ) { return; + } wp_redirect( $link, 301 ); // Permanent redirect exit; diff --git a/tests/phpunit/tests/rewrite/oldSlugRedirect.php b/tests/phpunit/tests/rewrite/oldSlugRedirect.php new file mode 100644 index 0000000000..a166d432be --- /dev/null +++ b/tests/phpunit/tests/rewrite/oldSlugRedirect.php @@ -0,0 +1,150 @@ +post_id = $this->factory->post->create( array( + 'post_title' => 'Foo Bar', + 'post_name' => 'foo-bar', + ) ); + + add_filter( 'old_slug_redirect_url', array( $this, 'filter_old_slug_redirect_url' ), 10, 1 ); + + global $wp_rewrite; + + $wp_rewrite->init(); + $wp_rewrite->set_permalink_structure( '/%postname%/' ); + add_rewrite_endpoint( 'custom-endpoint', EP_PERMALINK ); + add_rewrite_endpoint( 'second-endpoint', EP_PERMALINK, 'custom' ); + $wp_rewrite->flush_rules(); + } + + public function tearDown() { + parent::tearDown(); + + $this->old_slug_redirect_url = null; + + remove_filter( 'old_slug_redirect_url', array( $this, 'filter_old_slug_redirect_url' ), 10 ); + + global $wp_rewrite; + + $wp_rewrite->set_permalink_structure( '' ); + $wp_rewrite->init(); + } + + public function test_old_slug_redirect() { + $old_permalink = user_trailingslashit( get_permalink( $this->post_id ) ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $permalink = user_trailingslashit( get_permalink( $this->post_id ) ); + + $this->go_to( $old_permalink ); + wp_old_slug_redirect(); + $this->assertEquals( $permalink, $this->old_slug_redirect_url ); + } + + public function test_old_slug_redirect_endpoint() { + $old_permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'custom-endpoint' ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'custom-endpoint' ); + + $this->go_to( $old_permalink ); + $GLOBALS['wp_query']->query_vars['custom-endpoint'] = true; + wp_old_slug_redirect(); + $this->assertEquals( $permalink, $this->old_slug_redirect_url ); + } + + public function test_old_slug_redirect_endpoint_custom_query_var() { + $old_permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'second-endpoint' ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'second-endpoint' ); + + $this->go_to( $old_permalink ); + $GLOBALS['wp_query']->query_vars['custom'] = true; + wp_old_slug_redirect(); + $this->assertEquals( $permalink, $this->old_slug_redirect_url ); + } + + public function test_old_slug_redirect_feed() { + $old_permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'feed' ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'feed' ); + + $this->go_to( $old_permalink ); + wp_old_slug_redirect(); + $this->assertEquals( $permalink, $this->old_slug_redirect_url ); + } + + public function test_old_slug_redirect_attachment() { + $file = DIR_TESTDATA . '/images/canola.jpg'; + $attachment_id = $this->factory->attachment->create_object( $file, $this->post_id, array( + 'post_mime_type' => 'image/jpeg', + 'post_name' => 'my-attachment', + ) ); + + $old_permalink = get_attachment_link( $attachment_id ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $this->go_to( $old_permalink ); + wp_old_slug_redirect(); + $this->assertNull( $this->old_slug_redirect_url ); + $this->assertQueryTrue( 'is_attachment', 'is_singular', 'is_single' ); + } + + public function test_old_slug_redirect_paged() { + wp_update_post( array( + 'ID' => $this->post_id, + 'post_content' => 'TestTest', + ) ); + + $old_permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'page/2' ); + + wp_update_post( array( + 'ID' => $this->post_id, + 'post_name' => 'bar-baz', + ) ); + + $permalink = user_trailingslashit( trailingslashit( get_permalink( $this->post_id ) ) . 'page/2' ); + + $this->go_to( $old_permalink ); + wp_old_slug_redirect(); + $this->assertEquals( $permalink, $this->old_slug_redirect_url ); + } + + public function filter_old_slug_redirect_url( $url ) { + $this->old_slug_redirect_url = $url; + return false; + } +}