[wp-trac] [WordPress Trac] #43271: Issue with term duplicate check in wp_insert_term

WordPress Trac noreply at wordpress.org
Fri Feb 9 16:31:39 UTC 2018


#43271: Issue with term duplicate check in wp_insert_term
-------------------------+-----------------------------
 Reporter:  strategio    |      Owner:
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  Taxonomy     |    Version:  4.9.4
 Severity:  normal       |   Keywords:
  Focuses:               |
-------------------------+-----------------------------
 In WPML, we assume that a term can be duplicated in the same taxonomy in a
 secondary language. This means that it will have the same 'slug' as the
 one in the primary language.

 Here's a practical example of 2 term links from the same taxonomy with the
 same slug:
 - http://example.org/city/paris/
 - http://example.org/fr/city/paris/

 In `wp_insert_term` we have several checks to ensure that a term is unique
 in its taxonomy. All these checks can be overpassed with the standard WP
 API '''except the last one''' which makes a direct call to the database:

 {{{
 /*
  * Sanity check: if we just created a term with the same parent + taxonomy
 + slug but a higher term_id than
  * an existing term, then we have unwittingly created a duplicate term.
 Delete the dupe, and use the term_id
  * and term_taxonomy_id of the older term instead. Then return out of the
 function so that the "create" hooks
  * are not fired.
  */
 $duplicate_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.term_id,
 tt.term_taxonomy_id FROM $wpdb->terms t INNER JOIN $wpdb->term_taxonomy tt
 ON ( tt.term_id = t.term_id ) WHERE t.slug = %s AND tt.parent = %d AND
 tt.taxonomy = %s AND t.term_id < %d AND tt.term_taxonomy_id != %d", $slug,
 $parent, $taxonomy, $term_id, $tt_id ) );
 if ( $duplicate_term ) {
         $wpdb->delete( $wpdb->terms, array( 'term_id' => $term_id ) );
         $wpdb->delete( $wpdb->term_taxonomy, array( 'term_taxonomy_id' =>
 $tt_id ) );

         $term_id = (int) $duplicate_term->term_id;
         $tt_id   = (int) $duplicate_term->term_taxonomy_id;

         clean_term_cache( $term_id, $taxonomy );
         return array( 'term_id' => $term_id, 'term_taxonomy_id' => $tt_id
 );
 }
 }}}

 The above data validation is only performed in `wp_insert_term` and not in
 `wp_update_term` which makes the data validation inconsistent between the
 two function. This also allowed us to demonstrate that two terms with the
 same slug can live together in the same taxonomy.

 As a suggestion, this last check could be either:
 - '''removed''': since we already have several checks before and it's not
 performed when a term is updated.
 - '''filterable''': by using `get_term_by` to fetch the potential existing
 term, or having a specific filter hook (e.g.
 `wp_bypass_term_duplication_check`).

--
Ticket URL: <https://core.trac.wordpress.org/ticket/43271>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list