WordPress.org

Make WordPress Core

Ticket #30335: 30335.6.patch

File 30335.6.patch, 13.4 KB (added by mboynes, 5 years ago)

Update default categories if they get split; add taxonomy to split_shared_term action

  • src/wp-includes/category-template.php

     
    402402                        $output .= "\t<option value='" . esc_attr( $option_none_value ) . "'$selected>$show_option_none</option>\n";
    403403                }
    404404
     405                if ( $r['selected'] ) {
     406                        // Check if the 'selected' term was split
     407                        $selected_term = get_term( $r['selected'], $r['taxonomy'] );
     408                        if ( $selected_term && ! is_wp_error( $selected_term ) && intval( $r['selected'] ) != $selected_term->term_id ) {
     409                                $r['selected'] = $selected_term->term_id;
     410                        }
     411                }
     412
    405413                if ( $r['hierarchical'] ) {
    406414                        $depth = $r['depth'];  // Walk the full depth.
    407415                } else {
  • src/wp-includes/default-filters.php

     
    306306add_filter( 'determine_current_user', 'wp_validate_auth_cookie'          );
    307307add_filter( 'determine_current_user', 'wp_validate_logged_in_cookie', 20 );
    308308
     309// Split term updates
     310add_filter( 'split_shared_term', '_wp_check_split_default_terms', 10, 4 );
     311
    309312unset($filter, $action);
  • src/wp-includes/taxonomy.php

     
    12331233                                " );
    12341234                                break;
    12351235                        default:
    1236                                 $terms = implode( ',', array_map( 'intval', $query['terms'] ) );
     1236                                $terms = $query['terms'];
     1237
     1238                                // If any passed term_ids were previously split, substitute the correct term_id.
     1239                                foreach ( $terms as $term_index => $term_id ) {
     1240                                        if ( $split_term = _get_split_term( $term_id, $query['taxonomy'] ) ) {
     1241                                                $terms[ $term_index ] = $split_term;
     1242                                        }
     1243                                }
     1244
     1245                                $terms = implode( ',', array_map( 'intval', $terms ) );
     1246
    12371247                                $terms = $wpdb->get_col( "
    12381248                                        SELECT $resulting_field
    12391249                                        FROM $wpdb->term_taxonomy
     
    13151325                        return null;
    13161326                if ( ! $_term = wp_cache_get( $term, $taxonomy . ':terms:' . $incrementor ) ) {
    13171327                        $_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND t.term_id = %d LIMIT 1", $taxonomy, $term) );
     1328
     1329                        // If no term is found, check whether this was a previously split term.
     1330                        if ( ! $_term && $old_term_id = _get_split_term( $term, $taxonomy ) ) {
     1331                                return get_term( $old_term_id, $taxonomy, $output, $filter );
     1332                        }
     1333
    13181334                        if ( ! $_term )
    13191335                                return null;
    13201336                        wp_cache_add( $term, $_term, $taxonomy . ':terms:' . $incrementor );
     
    16751691         */
    16761692        $args = apply_filters( 'get_terms_args', $args, $taxonomies );
    16771693
     1694        /*
     1695         * For parameters that accept term_ids, check to see whether any of the IDs passed to the parameter correspond
     1696         * to previously split taxonomy terms. If so, swap out the old term_id for the new one, so the query matches.
     1697         */
     1698        $term_id_params = array( 'exclude', 'exclude_tree', 'include', 'parent', 'child_of' );
     1699        foreach ( $term_id_params as $term_id_param ) {
     1700                if ( empty( $args[ $term_id_param ] ) ) {
     1701                        continue;
     1702                }
     1703
     1704                $param_is_array = is_array( $args[ $term_id_param ] );
     1705
     1706                $passed_term_ids = (array) $args[ $term_id_param ];
     1707                foreach ( $passed_term_ids as $passed_term_index => $passed_term_id ) {
     1708                        foreach ( $taxonomies as $taxonomy ) {
     1709                                if ( $split_term = _get_split_term( $passed_term_id, $taxonomy ) ) {
     1710                                        $passed_term_ids[ $passed_term_index ] = $split_term;
     1711                                        continue 2;
     1712                                }
     1713                        }
     1714                }
     1715
     1716                if ( $param_is_array ) {
     1717                        $args[ $term_id_param ] = $passed_term_ids;
     1718                } else {
     1719                        $args[ $term_id_param ] = $passed_term_ids[0];
     1720                }
     1721        }
     1722
    16781723        $child_of = $args['child_of'];
    16791724        if ( $child_of ) {
    16801725                $hierarchy = _get_term_hierarchy( reset( $taxonomies ) );
     
    39033948}
    39043949
    39053950/**
     3951 * Look up a previously split taxonomy term by its old term_id.
     3952 *
     3953 * Terms that have been split by _split_shared_term() are stored, so that
     3954 * attempts to retrieve terms by the previous term_id still work.
     3955 *
     3956 * @since 4.1.0
     3957 * @access private
     3958 *
     3959 * @param int    $old_term_id Old, pre-split term_id.
     3960 * @param string $taxonomy    Taxonomy name.
     3961 */
     3962function _get_split_term( $old_term_id, $taxonomy ) {
     3963        $split_terms = get_option( '_split_terms_' . $taxonomy );
     3964
     3965        return ! empty( $split_terms[ $old_term_id ] ) ? $split_terms[ $old_term_id ] : null;
     3966}
     3967
     3968/**
    39063969 * Add count of children to parent count.
    39073970 *
    39083971 * Recalculates term counts by including items from child terms. Assumes all
     
    41154178                clean_term_cache( $term_id, $shared_term_taxonomy );
    41164179        }
    41174180
     4181        // Keep a record of term_ids that have been split, keyed by old term_id.
     4182        $split_term_data = get_option( '_split_terms_' . $term_taxonomy->taxonomy, array() );
     4183        $split_term_data[ $term_id ] = $new_term_id;
     4184        if ( false === get_option( '_split_terms_' . $term_taxonomy->taxonomy, false ) ) {
     4185                add_option( '_split_terms_' . $term_taxonomy->taxonomy, $split_term_data, '', 'no' );
     4186        } else {
     4187                update_option( '_split_terms_' . $term_taxonomy->taxonomy, $split_term_data );
     4188        }
     4189
    41184190        /**
    41194191         * Fires after a previously shared taxonomy term is split into two separate terms.
    41204192         *
    41214193         * @since 4.1.0
    41224194         *
    4123          * @param int $term_id          ID of the formerly shared term.
    4124          * @param int $new_term_id      ID of the new term created for the $term_taxonomy_id.
    4125          * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
     4195         * @param int    $term_id          ID of the formerly shared term.
     4196         * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
     4197         * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
     4198         * @param string $taxonomy         Taxonomy for the split term.
    41264199         */
    4127         do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id );
     4200        do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id, $term_taxonomy->taxonomy );
    41284201
    41294202        return $new_term_id;
    41304203}
    41314204
    41324205/**
     4206 * Check default categories when a term gets split to see if any of them need
     4207 * to be updated.
     4208 *
     4209 * @since 4.1.0
     4210 * @access private
     4211 *
     4212 * @param int    $term_id          ID of the formerly shared term.
     4213 * @param int    $new_term_id      ID of the new term created for the $term_taxonomy_id.
     4214 * @param int    $term_taxonomy_id ID for the term_taxonomy row affected by the split.
     4215 * @param string $taxonomy         Taxonomy for the split term.
     4216 */
     4217function _wp_check_split_default_terms( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
     4218        if ( 'category' == $taxonomy ) {
     4219                foreach ( array( 'default_category', 'default_link_category', 'default_email_category' ) as $option ) {
     4220                        if ( $term_id == get_option( $option, -1 ) ) {
     4221                                update_option( $option, $new_term_id );
     4222                        }
     4223                }
     4224        }
     4225}
     4226
     4227/**
    41334228 * Generate a permalink for a taxonomy term archive.
    41344229 *
    41354230 * @since 2.5.0
  • tests/phpunit/tests/term/splitSharedTerm.php

     
    44 * @group taxonomy
    55 */
    66class Tests_Term_SplitSharedTerm extends WP_UnitTestCase {
    7         protected $tt_ids = array();
     7        protected $terms = array();
    88
    99        public function setUp() {
    1010                global $wpdb;
     
    4040                        'parent' => $t1['term_id'],
    4141                ) );
    4242
    43                 $this->tt_ids = array(
    44                         't1' => $t1['term_taxonomy_id'],
    45                         't2' => $t2['term_taxonomy_id'],
    46                         't3' => $t3['term_taxonomy_id'],
    47                         't2_child' => $t2_child['term_taxonomy_id'],
     43                $this->terms = array(
     44                        't1' => $t1,
     45                        't2' => $t2,
     46                        't3' => $t3,
     47                        't2_child' => $t2_child,
    4848                );
    4949
    5050                _split_shared_term( $t1['term_id'], $t2['term_taxonomy_id'] );
     
    5555         * @ticket 5809
    5656         */
    5757        public function test_should_create_new_term_ids() {
    58                 $t1_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t1'], 'wptests_tax' );
    59                 $t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
    60                 $t3_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t3'], 'wptests_tax_3' );
     58                $t1_term = get_term_by( 'term_taxonomy_id', $this->terms['t1']['term_taxonomy_id'], 'wptests_tax' );
     59                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     60                $t3_term = get_term_by( 'term_taxonomy_id', $this->terms['t3']['term_taxonomy_id'], 'wptests_tax_3' );
    6161
    6262                $this->assertNotEquals( $t1_term->term_id, $t2_term->term_id );
    6363                $this->assertNotEquals( $t1_term->term_id, $t3_term->term_id );
     
    6868         * @ticket 5809
    6969         */
    7070        public function test_should_retain_child_terms_when_using_get_terms_parent() {
    71                 $t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
     71                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
    7272                $children = get_terms( 'wptests_tax_2', array(
    7373                        'parent' => $t2_term->term_id,
    7474                        'hide_empty' => false,
    7575                ) );
    7676
    77                 $this->assertEquals( $this->tt_ids['t2_child'], $children[0]->term_taxonomy_id );
     77                $this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
    7878        }
    7979
    8080        /**
    8181         * @ticket 5809
    8282         */
    8383        public function test_should_retain_child_terms_when_using_get_terms_child_of() {
    84                 $t2_term = get_term_by( 'term_taxonomy_id', $this->tt_ids['t2'], 'wptests_tax_2' );
     84                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
    8585                $children = get_terms( 'wptests_tax_2', array(
    8686                        'child_of' => $t2_term->term_id,
    8787                        'hide_empty' => false,
    8888                ) );
    8989
    90                 $this->assertEquals( $this->tt_ids['t2_child'], $children[0]->term_taxonomy_id );
     90                $this->assertEquals( $this->terms['t2_child']['term_taxonomy_id'], $children[0]->term_taxonomy_id );
    9191        }
    9292
    9393        /**
     
    121121                $t2_children = get_term_children( $t2['term_id'], 'wptests_tax_4' );
    122122                $this->assertEquals( array( $new_term_id ), $t2_children );
    123123        }
     124
     125        /**
     126         * @ticket 30335
     127         */
     128        public function test_should_remain_available_at_old_term_id_using_get_term_by() {
     129                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     130
     131                $this->assertEquals( $t2_term, get_term_by( 'id', $this->terms['t1']['term_id'], 'wptests_tax_2' ) );
     132        }
     133
     134        /**
     135         * @ticket 30335
     136         */
     137        public function test_should_remain_available_at_old_term_id_using_get_term() {
     138                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     139
     140                $this->assertEquals( $t2_term, get_term( intval( $this->terms['t1']['term_id'] ), 'wptests_tax_2' ) );
     141        }
     142
     143        /**
     144         * @ticket 30335
     145         */
     146        public function test_should_remain_available_at_old_term_id_using_get_terms_with_parent_param() {
     147                $found = get_terms( 'wptests_tax_2', array(
     148                        'parent' => $this->terms['t1']['term_id'],
     149                        'hide_empty' => false,
     150                ) );
     151                $this->assertEquals( $this->terms['t2_child']['term_id'], $found[0]->term_id );
     152        }
     153
     154        /**
     155         * @ticket 30335
     156         */
     157        public function test_should_remain_available_at_old_term_id_using_get_terms_with_include_param() {
     158                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     159
     160                $found = get_terms( 'wptests_tax_2', array(
     161                        'include' => array( $this->terms['t1']['term_id'] ),
     162                        'hide_empty' => false,
     163                ) );
     164                $this->assertEquals( $t2_term->term_id, $found[0]->term_id );
     165        }
     166
     167        /**
     168         * @ticket 30335
     169         */
     170        public function test_should_remain_available_at_old_term_id_using_tax_query() {
     171                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     172
     173                $tq = new WP_Tax_Query( array(
     174                        array(
     175                                'field' => 'term_id',
     176                                'taxonomy' => 'wptests_tax_2',
     177                                'terms' => array( $this->terms['t1']['term_id'] ),
     178                        ),
     179                ) );
     180                $tq->transform_query( $tq->queries[0], 'term_taxonomy_id' );
     181
     182                $this->assertEquals( array( $t2_term->term_taxonomy_id ), $tq->queries[0]['terms'] );
     183        }
     184
     185        /**
     186         * @ticket 30335
     187         */
     188        public function test_should_remain_available_at_old_term_id_using_wp_dropdown_categories() {
     189                $t2_term = get_term_by( 'term_taxonomy_id', $this->terms['t2']['term_taxonomy_id'], 'wptests_tax_2' );
     190                $terms = get_terms( 'wptests_tax_2', array( 'hide_empty' => false ) );
     191                $dropdown = wp_dropdown_categories( array(
     192                        'echo'       => false,
     193                        'taxonomy'   => 'wptests_tax_2',
     194                        'hide_empty' => false,
     195                        'selected'   => $this->terms['t1']['term_id'],
     196                ) );
     197
     198                $this->assertRegExp( "/<option[^>]+value=\"{$t2_term->term_id}\" selected=\"selected\">/", $dropdown );
     199        }
     200
     201        /**
     202         * @ticket 30335
     203         */
     204        public function test_should_update_default_category_on_term_split() {
     205                global $wpdb;
     206                $t1 = wp_insert_term( 'Foo Default', 'category' );
     207
     208                update_option( 'default_category', $t1['term_id'] );
     209
     210                register_taxonomy( 'wptests_tax_5', 'post' );
     211                $t2 = wp_insert_term( 'Foo Default', 'wptests_tax_5' );
     212
     213                // Manually modify because split terms shouldn't naturally occur.
     214                $wpdb->update( $wpdb->term_taxonomy,
     215                        array( 'term_id' => $t1['term_id'] ),
     216                        array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
     217                        array( '%d' ),
     218                        array( '%d' )
     219                );
     220
     221                $this->assertEquals( $t1['term_id'], get_option( 'default_category', -1 ) );
     222
     223                $new_term_id = _split_shared_term( $t1['term_id'], $t1['term_taxonomy_id'] );
     224
     225                $this->assertNotEquals( $new_term_id, $t1['term_id'] );
     226                $this->assertEquals( $new_term_id, get_option( 'default_category', -1 ) );
     227        }
    124228}