From 973223ad5fbc07a2c526dbccf48b50d76eef8c3f Mon Sep 17 00:00:00 2001 From: Boone Gorges Date: Wed, 4 Nov 2015 21:24:26 +0000 Subject: [PATCH] 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. Built from https://develop.svn.wordpress.org/trunk@35515 git-svn-id: http://core.svn.wordpress.org/trunk@35479 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/taxonomy-functions.php | 49 ++++++++++++++++++++++++++++-- wp-includes/version.php | 2 +- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/wp-includes/taxonomy-functions.php b/wp-includes/taxonomy-functions.php index 592966b681..3c7c60291a 100644 --- a/wp-includes/taxonomy-functions.php +++ b/wp-includes/taxonomy-functions.php @@ -1578,7 +1578,8 @@ function get_terms( $taxonomies, $args = '' ) { * @param mixed $meta_value Metadata value. * @param bool $unique Optional. Whether to bail if an entry with the same key is found for the term. * Default false. - * @return int|bool Meta ID on success, false on failure. + * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies. + * False on failure. */ function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) { // Bail if term meta table is not installed. @@ -1586,6 +1587,10 @@ function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) { return false; } + if ( wp_term_is_shared( $term_id ) ) { + return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.'), $term_id ); + } + $added = add_metadata( 'term', $term_id, $meta_key, $meta_value, $unique ); // Bust term query cache. @@ -1655,7 +1660,8 @@ function get_term_meta( $term_id, $key = '', $single = false ) { * @param string $meta_key Metadata key. * @param mixed $meta_value Metadata value. * @param mixed $prev_value Optional. Previous value to check before removing. - * @return int|bool Meta ID if the key didn't previously exist. True on successful update. False on failure. + * @return int|WP_Error|bool Meta ID if the key didn't previously exist. True on successful update. + * WP_Error when term_id is ambiguous between taxonomies. False on failure. */ function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) { // Bail if term meta table is not installed. @@ -1663,6 +1669,10 @@ function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) return false; } + if ( wp_term_is_shared( $term_id ) ) { + return new WP_Error( 'ambiguous_term_id', __( 'Term meta cannot be added to terms that are shared between taxonomies.'), $term_id ); + } + $updated = update_metadata( 'term', $term_id, $meta_key, $meta_value, $prev_value ); // Bust term query cache. @@ -4007,6 +4017,18 @@ function _split_shared_term( $term_id, $term_taxonomy_id, $record = true ) { update_option( '_split_terms', $split_term_data ); } + // If we've just split the final shared term, set the "finished" flag. + $shared_terms_exist = $wpdb->get_results( + "SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt + LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id + GROUP BY t.term_id + HAVING term_tt_count > 1 + LIMIT 1" + ); + if ( ! $shared_terms_exist ) { + update_option( 'finished_splitting_shared_terms', true ); + } + /** * Fires after a previously shared taxonomy term is split into two separate terms. * @@ -4254,6 +4276,29 @@ function wp_get_split_term( $old_term_id, $taxonomy ) { return $term_id; } +/** + * Determine whether a term is shared between multiple taxonomies. + * + * Shared taxonomy terms began to be split in 4.3, but failed cron tasks or other delays in upgrade routines may cause + * shared terms to remain. + * + * @since 4.4.0 + * + * @param int $term_id + * @return bool + */ +function wp_term_is_shared( $term_id ) { + global $wpdb; + + if ( get_option( 'finished_splitting_shared_terms' ) ) { + return false; + } + + $tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) ); + + return $tt_count > 1; +} + /** * Generate a permalink for a taxonomy term archive. * diff --git a/wp-includes/version.php b/wp-includes/version.php index f5fe45beaa..6b865419cd 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.4-beta2-35514'; +$wp_version = '4.4-beta2-35515'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.