WordPress.org

Make WordPress Core

Ticket #15953: 15953.patch

File 15953.patch, 7.5 KB (added by kevinlangleyjr, 3 years ago)
  • src/wp-includes/default-filters.php

     
    331331add_action( 'post_updated',       'wp_check_for_changed_slugs', 12, 3 );
    332332add_action( 'attachment_updated', 'wp_check_for_changed_slugs', 12, 3 );
    333333
     334// Redirect Old Term Slugs
     335add_action( 'template_redirect', 'wp_old_term_slug_redirect'              );
     336add_action( 'edited_term',       'wp_check_for_changed_term_slugs', 10, 5 );
     337
    334338// Nonce check for Post Previews
    335339add_action( 'init', '_show_post_preview' );
    336340
  • src/wp-includes/query.php

     
    920920}
    921921
    922922/**
     923 * Redirect old term slugs to the correct permalink.
     924 *
     925 * Attempts to find the current slug from the past slugs for a term.
     926 *
     927 * @since 4.7.1
     928 *
     929 * @global wpdb $wpdb WordPress database abstraction object.
     930 */
     931function wp_old_term_slug_redirect() {
     932        if( is_404() && '' !== get_query_var( 'taxonomy' ) && '' !== get_query_var( 'term' ) ) {
     933                global $wpdb;
     934
     935                $term_id = get_term( array(
     936                        'taxonomy' => get_query_var( 'taxonomy' ),
     937                        'fields' => 'ids',
     938                        'number' => 1,
     939                        'hide_empty' => false,
     940                        'meta_query' => array(
     941                                array(
     942                                        'key' => '_wp_old_slug',
     943                                        'value' => get_query_var( 'term' )
     944                                )
     945                        )
     946                ) );
     947
     948                if ( is_wp_error( $term_id ) || empty( $term_id ) ){
     949                        return;
     950                }
     951
     952                $link = get_term_link( $term_id[0], get_query_var( 'taxonomy' ) );
     953
     954                if ( isset( $GLOBALS['wp_query']->query_vars['paged'] ) && $GLOBALS['wp_query']->query_vars['paged'] > 1 ) {
     955                        $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . $GLOBALS['wp_query']->query_vars['paged'] );
     956                } elseif( is_embed() ) {
     957                        $link = user_trailingslashit( trailingslashit( $link ) . 'embed' );
     958                }
     959
     960                /**
     961                 * Filters the old term slug redirect URL.
     962                 *
     963                 * @since 4.7.1
     964                 *
     965                 * @param string $link The redirect URL.
     966                 */
     967                $link = apply_filters( 'old_term_slug_redirect_url', $link );
     968
     969                if ( ! $link ) {
     970                        return;
     971                }
     972
     973                wp_redirect( $link, 301 ); // Permanent redirect
     974                exit;
     975        }
     976}
     977
     978/**
    923979 * Set up global post data.
    924980 *
    925981 * @since 1.5.0
  • src/wp-includes/taxonomy.php

     
    25742574
    25752575        // First, get all of the original args
    25762576        $term = get_term( $term_id, $taxonomy );
     2577        $term_before = $term;
    25772578
    25782579        if ( is_wp_error( $term ) ) {
    25792580                return $term;
     
    27692770
    27702771        clean_term_cache($term_id, $taxonomy);
    27712772
     2773        $term_after = get_term( $term_id );
     2774
    27722775        /**
    27732776         * Fires after a term has been updated, and the term cache has been cleaned.
    27742777         *
    27752778         * @since 2.3.0
    27762779         *
    2777          * @param int    $term_id  Term ID.
    2778          * @param int    $tt_id    Term taxonomy ID.
    2779          * @param string $taxonomy Taxonomy slug.
     2780         * @param int     $term_id      Term ID.
     2781         * @param int     $tt_id        Term taxonomy ID.
     2782         * @param string  $taxonomy     Taxonomy slug.
     2783         * @param WP_Term $term_after   Term object following the update.
     2784         * @param WP_Term $term_before  Term object before the update.
    27802785         */
    2781         do_action( "edited_term", $term_id, $tt_id, $taxonomy );
     2786        do_action( "edited_term", $term_id, $tt_id, $taxonomy, $term_after, $term_before );
    27822787
    27832788        /**
    27842789         * Fires after a term for a specific taxonomy has been updated, and the term
     
    42274232
    42284233        return $parent;
    42294234}
     4235
     4236/**
     4237 * Check for changed slugs for the term and save the old slug.
     4238 *
     4239 * The function is used when a term is updated,
     4240 * by comparing the current and previous term objects.
     4241 *
     4242 * If the slug was changed and not already part of the old slugs then it will be
     4243 * added to the term meta field ('_wp_old_slug') for storing old slugs for
     4244 * that term.
     4245 *
     4246 * The most logically usage of this function is redirecting changed term objects, so
     4247 * that those that linked to a changed term will be redirected to the new term.
     4248 *
     4249 * @since 4.7.1
     4250 *
     4251 * @param int      $term_id      Term ID.
     4252 * @param int      $tt_id        Taxonomy Term ID.
     4253 * @param string   $taxonomy     Taxonomy
     4254 * @param WP_Term  $term_after   Term object following the update
     4255 * @param WP_Term  $term_before  Term object before the update
     4256 */
     4257function wp_check_for_changed_term_slugs( $term_id, $tt_id, $taxonomy, $term_after, $term_before ) {
     4258        // Don't bother if it hasn't changed.
     4259        if ( $term_after->slug == $term_before->slug ) {
     4260                return;
     4261        }
     4262
     4263        $old_slugs = (array) get_term_meta( $term_id, '_wp_old_slug' );
     4264
     4265        // If we haven't added this old slug before, add it now.
     4266        if ( ! empty( $term_before->slug ) && ! in_array( $term_before->slug, $old_slugs ) ) {
     4267                add_term_meta( $term_id, '_wp_old_slug', $term_before->slug );
     4268        }
     4269
     4270        // If the new slug was used previously, delete it from the list.
     4271        if ( in_array( $term_after->slug, $old_slugs ) ) {
     4272                delete_term_meta( $term_id, '_wp_old_slug', $term_after->slug );
     4273        }
     4274}
  • tests/phpunit/tests/rewrite/oldTermSlugRedirect.php

     
     1<?php
     2
     3/**
     4 * @group rewrite
     5 * @ticket 15953
     6 */
     7class Tests_Rewrite_OldTermSlugRedirect extends WP_UnitTestCase {
     8        protected $old_term_slug_redirect_url;
     9
     10        protected $term_id;
     11
     12        public function setUp() {
     13                global $wp_rewrite;
     14
     15                parent::setUp();
     16
     17                $this->set_permalink_structure( '/%postname%/' );
     18
     19                register_taxonomy( 'wptests_tax', array( 'post' ) );
     20
     21                $this->term_id = self::factory()->term->create( array(
     22                        'taxonomy' => 'wptests_tax',
     23                        'name' => 'Foo Bar',
     24                        'slug' => 'foo-bar'
     25                ) );
     26
     27                $wp_rewrite->flush_rules();
     28
     29                add_filter( 'old_term_slug_redirect_url', array( $this, 'filter_old_term_slug_redirect_url' ), 10, 1 );
     30        }
     31
     32        public function tearDown() {
     33                parent::tearDown();
     34
     35                $this->old_term_slug_redirect_url = null;
     36
     37                remove_filter( 'old_term_slug_redirect_url', array( $this, 'filter_old_term_slug_redirect_url' ), 10 );
     38        }
     39
     40        public function test_old_term_slug_redirect() {
     41                $old_permalink = user_trailingslashit( get_term_link( $this->term_id, 'wptests_tax' ) );
     42
     43                wp_update_term( $this->term_id, 'wptests_tax', array(
     44                        'slug' => 'bar-baz'
     45                ) );
     46
     47                $permalink = user_trailingslashit( get_term_link( $this->term_id, 'wptests_tax' ) );
     48
     49                $this->go_to( $old_permalink );
     50                wp_old_term_slug_redirect();
     51                $this->assertEquals( $permalink, $this->old_term_slug_redirect_url );
     52        }
     53
     54        public function test_old_slug_doesnt_redirect_when_reused() {
     55                $old_permalink = user_trailingslashit( get_term_link( $this->term_id ) );
     56
     57                wp_update_term( $this->term_id, 'wptests_tax', array(
     58                        'slug' => 'bar-baz',
     59                ) );
     60
     61                $new_term_id = self::factory()->term->create( array(
     62                        'taxonomy' => 'wptests_tax',
     63                        'name'     => 'Foo Bar',
     64                        'slug'     => 'foo-bar'
     65                ) );
     66
     67                $permalink = user_trailingslashit( get_term_link( $new_term_id ) );
     68
     69                $this->assertEquals( $old_permalink, $permalink );
     70
     71                $this->go_to( $old_permalink );
     72                wp_old_term_slug_redirect();
     73                $this->assertNull( $this->old_term_slug_redirect_url );
     74        }
     75
     76        public function filter_old_term_slug_redirect_url( $url ) {
     77                $this->old_term_slug_redirect_url = $url;
     78                return false;
     79        }
     80}