Make WordPress Core

Changeset 35515


Ignore:
Timestamp:
11/04/2015 09:23:28 PM (9 years ago)
Author:
boonebgorges
Message:

Don't allow term meta to be added to shared taxonomy terms.

add_term_meta() and update_term_meta() identify terms by $term_id. In
cases where a term is shared between taxonomies, $term_id is insufficient to
distinguish where the metadata belongs.

When attempting to add/update termmeta on a shared term, a WP_Error object
is returned. This gives developers enough information to decide whether they'd
like to force the term to be split and retry the save, or show an error in the
UI, or whatever.

Props boonebgorges, mboynes, DH-Shredder, jorbin, aaroncampbell.
Fixes #34544.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/taxonomy-functions.php

    r35504 r35515  
    15791579 * @param bool   $unique     Optional. Whether to bail if an entry with the same key is found for the term.
    15801580 *                           Default false.
    1581  * @return int|bool Meta ID on success, false on failure.
     1581 * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies.
     1582 *                           False on failure.
    15821583 */
    15831584function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {
     
    15851586    if ( get_option( 'db_version' ) < 34370 ) {
    15861587        return false;
     1588    }
     1589
     1590    if ( wp_term_is_shared( $term_id ) ) {
     1591        return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.'), $term_id );
    15871592    }
    15881593
     
    16561661 * @param mixed  $meta_value Metadata value.
    16571662 * @param mixed  $prev_value Optional. Previous value to check before removing.
    1658  * @return int|bool Meta ID if the key didn't previously exist. True on successful update. False on failure.
     1663 * @return int|WP_Error|bool Meta ID if the key didn't previously exist. True on successful update.
     1664 *                           WP_Error when term_id is ambiguous between taxonomies. False on failure.
    16591665 */
    16601666function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {
     
    16621668    if ( get_option( 'db_version' ) < 34370 ) {
    16631669        return false;
     1670    }
     1671
     1672    if ( wp_term_is_shared( $term_id ) ) {
     1673        return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.'), $term_id );
    16641674    }
    16651675
     
    40084018    }
    40094019
     4020    // If we've just split the final shared term, set the "finished" flag.
     4021    $shared_terms_exist = $wpdb->get_results(
     4022        "SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
     4023         LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
     4024         GROUP BY t.term_id
     4025         HAVING term_tt_count > 1
     4026         LIMIT 1"
     4027    );
     4028    if ( ! $shared_terms_exist ) {
     4029        update_option( 'finished_splitting_shared_terms', true );
     4030    }
     4031
    40104032    /**
    40114033     * Fires after a previously shared taxonomy term is split into two separate terms.
     
    42534275
    42544276    return $term_id;
     4277}
     4278
     4279/**
     4280 * Determine whether a term is shared between multiple taxonomies.
     4281 *
     4282 * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or other delays in upgrade routines may cause
     4283 * shared terms to remain.
     4284 *
     4285 * @since 4.4.0
     4286 *
     4287 * @param int $term_id
     4288 * @return bool
     4289 */
     4290function wp_term_is_shared( $term_id ) {
     4291    global $wpdb;
     4292
     4293    if ( get_option( 'finished_splitting_shared_terms' ) ) {
     4294        return false;
     4295    }
     4296
     4297    $tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
     4298
     4299    return $tt_count > 1;
    42554300}
    42564301
  • trunk/tests/phpunit/tests/term/meta.php

    r35242 r35515  
    308308    }
    309309
     310    /**
     311     * @ticket 34544
     312     */
     313    public function test_add_term_meta_should_return_error_when_term_id_is_shared() {
     314        global $wpdb;
     315
     316        update_option( 'finished_splitting_shared_terms', false );
     317
     318        register_taxonomy( 'wptests_tax', 'post' );
     319        register_taxonomy( 'wptests_tax_2', 'post' );
     320        register_taxonomy( 'wptests_tax_3', 'post' );
     321
     322        $t1 = wp_insert_term( 'Foo', 'wptests_tax' );
     323        $t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
     324        $t3 = wp_insert_term( 'Foo', 'wptests_tax_3' );
     325
     326        // Manually modify because shared terms shouldn't naturally occur.
     327        $wpdb->update( $wpdb->term_taxonomy,
     328            array( 'term_id' => $t1['term_id'] ),
     329            array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
     330            array( '%d' ),
     331            array( '%d' )
     332        );
     333
     334        $wpdb->update( $wpdb->term_taxonomy,
     335            array( 'term_id' => $t1['term_id'] ),
     336            array( 'term_taxonomy_id' => $t3['term_taxonomy_id'] ),
     337            array( '%d' ),
     338            array( '%d' )
     339        );
     340
     341        $found = add_term_meta( $t1['term_id'], 'bar', 'baz' );
     342        $this->assertWPError( $found );
     343        $this->assertSame( 'ambiguous_term_id', $found->get_error_code() );
     344    }
     345
     346    /**
     347     * @ticket 34544
     348     */
     349    public function test_update_term_meta_should_return_error_when_term_id_is_shared() {
     350        global $wpdb;
     351
     352        update_option( 'finished_splitting_shared_terms', false );
     353
     354        register_taxonomy( 'wptests_tax', 'post' );
     355        $t1 = wp_insert_term( 'Foo', 'wptests_tax' );
     356        add_term_meta( $t1, 'foo', 'bar' );
     357
     358        register_taxonomy( 'wptests_tax_2', 'post' );
     359        register_taxonomy( 'wptests_tax_3', 'post' );
     360
     361        $t2 = wp_insert_term( 'Foo', 'wptests_tax_2' );
     362        $t3 = wp_insert_term( 'Foo', 'wptests_tax_3' );
     363
     364        // Manually modify because shared terms shouldn't naturally occur.
     365        $wpdb->update( $wpdb->term_taxonomy,
     366            array( 'term_id' => $t1['term_id'] ),
     367            array( 'term_taxonomy_id' => $t2['term_taxonomy_id'] ),
     368            array( '%d' ),
     369            array( '%d' )
     370        );
     371
     372        $wpdb->update( $wpdb->term_taxonomy,
     373            array( 'term_id' => $t1['term_id'] ),
     374            array( 'term_taxonomy_id' => $t3['term_taxonomy_id'] ),
     375            array( '%d' ),
     376            array( '%d' )
     377        );
     378
     379        $found = update_term_meta( $t1['term_id'], 'foo', 'baz' );
     380        $this->assertWPError( $found );
     381        $this->assertSame( 'ambiguous_term_id', $found->get_error_code() );
     382    }
     383
    310384    public static function set_cache_results( $q ) {
    311385        $q->set( 'cache_results', true );
Note: See TracChangeset for help on using the changeset viewer.