Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/wp-includes/taxonomy.php
Original file line number Diff line number Diff line change
Expand Up @@ -2401,6 +2401,41 @@ function wp_get_object_terms( $object_ids, $taxonomies, $args = array() ) {
return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args );
}

/**
* Checks a term name against the maximum length allowed by the `wp_terms` table's `name` column.
*
* @since 7.2.0
* @access private
*
* @global wpdb $wpdb WordPress database abstraction object.
*
* @param string $name Term name to check.
* @return true|WP_Error True if the name fits the column, WP_Error otherwise.
*/
function _wp_check_term_name_length( $name ) {
global $wpdb;

$max_length = 200;
$col_length = $wpdb->get_col_length( $wpdb->terms, 'name' );

if ( is_array( $col_length ) && ! empty( $col_length['length'] ) ) {
$max_length = (int) $col_length['length'];
}

if ( mb_strlen( $name ) > $max_length ) {
return new WP_Error(
'term_name_too_long',
sprintf(
/* translators: %d: Maximum number of characters. */
__( 'Term name may not be longer than %d characters.' ),
$max_length
)
);
}

return true;
}

/**
* Adds a new term to the database.
*
Expand Down Expand Up @@ -2520,6 +2555,11 @@ function wp_insert_term( $term, $taxonomy, $args = array() ) {
return new WP_Error( 'invalid_term_name', __( 'Invalid term name.' ) );
}

$name_length_error = _wp_check_term_name_length( $name );
if ( is_wp_error( $name_length_error ) ) {
return $name_length_error;
}

$slug_provided = ! empty( $args['slug'] );
if ( ! $slug_provided ) {
$slug = sanitize_title( $name );
Expand Down Expand Up @@ -3312,6 +3352,11 @@ function wp_update_term( $term_id, $taxonomy, $args = array() ) {
return new WP_Error( 'empty_term_name', __( 'A name is required for this term.' ) );
}

$name_length_error = _wp_check_term_name_length( $name );
if ( is_wp_error( $name_length_error ) ) {
return $name_length_error;
}

if ( (int) $parsed_args['parent'] > 0 && ! term_exists( (int) $parsed_args['parent'] ) ) {
return new WP_Error( 'missing_parent', __( 'Parent term does not exist.' ) );
}
Expand Down
33 changes: 33 additions & 0 deletions tests/phpunit/tests/term/wpInsertTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,39 @@ public function test_wp_insert_term_with_empty_name_after_db_sanitization() {
$this->assertSame( 'invalid_term_name', $term->get_error_code() );
}

/**
* @ticket 36610
*/
public function test_wp_insert_term_name_too_long_should_return_wp_error() {
register_taxonomy( 'wptests_tax', 'post' );
$found = wp_insert_term( str_repeat( 'a', 201 ), 'wptests_tax' );

$this->assertWPError( $found );
$this->assertSame( 'term_name_too_long', $found->get_error_code() );
}

/**
* @ticket 36610
*/
public function test_wp_insert_term_name_at_max_length_should_succeed() {
register_taxonomy( 'wptests_tax', 'post' );
$found = wp_insert_term( str_repeat( 'a', 200 ), 'wptests_tax' );

$this->assertNotWPError( $found );
}

/**
* @ticket 36610
*/
public function test_wp_insert_term_name_length_should_be_counted_in_characters_not_bytes() {
register_taxonomy( 'wptests_tax', 'post' );

// 200 multibyte characters fit the column, even though their byte length is far greater than 200.
$found = wp_insert_term( str_repeat( 'é', 200 ), 'wptests_tax' );

$this->assertNotWPError( $found );
}

/** Helpers */

public function deleted_term_cb( $term, $tt_id, $taxonomy, $deleted_term, $object_ids ) {
Expand Down
41 changes: 41 additions & 0 deletions tests/phpunit/tests/term/wpUpdateTerm.php
Original file line number Diff line number Diff line change
Expand Up @@ -802,4 +802,45 @@ public function test_wp_update_term_with_null_get_term() {
$this->assertWPError( $found );
$this->assertSame( 'invalid_term', $found->get_error_code() );
}

/**
* @ticket 36610
*/
public function test_wp_update_term_name_too_long_should_return_wp_error() {
register_taxonomy( 'wptests_tax', 'post' );
$t = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax' ) );

$found = wp_update_term(
$t,
'wptests_tax',
array(
'name' => str_repeat( 'a', 201 ),
)
);

_unregister_taxonomy( 'wptests_tax' );

$this->assertWPError( $found );
$this->assertSame( 'term_name_too_long', $found->get_error_code() );
}

/**
* @ticket 36610
*/
public function test_wp_update_term_name_at_max_length_should_succeed() {
register_taxonomy( 'wptests_tax', 'post' );
$t = self::factory()->term->create( array( 'taxonomy' => 'wptests_tax' ) );

$found = wp_update_term(
$t,
'wptests_tax',
array(
'name' => str_repeat( 'a', 200 ),
)
);

_unregister_taxonomy( 'wptests_tax' );

$this->assertNotWPError( $found );
}
}
Loading