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
52 changes: 38 additions & 14 deletions src/js/_enqueues/admin/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ jQuery( function($) {

var addingTerm = false;

/**
* Updates the displaying-num span with the new total item count.
*
* @since 6.8.0
*
* @param {number} total The new total number of items.
* @return {void}
*/
function updateDisplayingNum( total ) {
$( '.displaying-num' ).text(
wp.i18n.sprintf(
/* translators: %s: Number of items. */
wp.i18n._n( '%s item', '%s items', total ),
total.toLocaleString()
)
);
}

/**
* Adds an event handler to the delete term link on the term overview page.
*
Expand Down Expand Up @@ -45,10 +63,11 @@ jQuery( function($) {
*
* @return {void}
*/
$.post(ajaxurl, data, function(r){
$.post( ajaxurl, data, function( r ) {
var message;
if ( '1' == r ) {
$('#ajax-response').empty();

if ( r && r.success ) {
$( '#ajax-response' ).empty();
let nextFocus = tr.next( 'tr' ).find( 'a.row-title' );
let prevFocus = tr.prev( 'tr' ).find( 'a.row-title' );
// If there is neither a next row or a previous row, focus the tag input field.
Expand All @@ -60,7 +79,7 @@ jQuery( function($) {
}
}

tr.fadeOut('normal', function(){ tr.remove(); });
tr.fadeOut( 'normal', function() { tr.remove(); } );

/**
* Removes the term from the parent box and the tag cloud.
Expand All @@ -69,23 +88,25 @@ jQuery( function($) {
* This term ID is then used to select the relevant HTML elements:
* The parent box and the tag cloud.
*/
$('select#parent option[value="' + data.match(/tag_ID=(\d+)/)[1] + '"]').remove();
$('a.tag-link-' + data.match(/tag_ID=(\d+)/)[1]).remove();
$( 'select#parent option[value="' + data.match( /tag_ID=(\d+)/ )[1] + '"]' ).remove();
$( 'a.tag-link-' + data.match( /tag_ID=(\d+)/ )[1] ).remove();
nextFocus.trigger( 'focus' );
updateDisplayingNum( r.data.total );
message = wp.i18n.__( 'The selected tag has been deleted.' );
} else if ( '-1' == r ) {

} else if ( '-1' === r ) {
message = wp.i18n.__( 'Sorry, you are not allowed to do that.' );
$('#ajax-response').empty().append('<div class="notice notice-error"><p>' + message + '</p></div>');
$( '#ajax-response' ).empty().append( '<div class="notice notice-error"><p>' + message + '</p></div>' );
resetRowAfterFailure( tr );

} else {
message = wp.i18n.__( 'An error occurred while processing your request. Please try again later.' );
$('#ajax-response').empty().append('<div class="notice notice-error"><p>' + message + '</p></div>');
$( '#ajax-response' ).empty().append( '<div class="notice notice-error"><p>' + message + '</p></div>' );
resetRowAfterFailure( tr );
}

wp.a11y.speak( message, 'assertive' );
});
} );
}

return false;
Expand Down Expand Up @@ -179,19 +200,22 @@ jQuery( function($) {

$('.tags .no-items').remove();

if ( form.find('select#parent') ) {
if ( form.find( 'select#parent' ) ) {
// Parents field exists, Add new term to the list.
term = res.responses[1].supplemental;

// Create an indent for the Parent field.
indent = '';
for ( i = 0; i < res.responses[1].position; i++ )
for ( i = 0; i < res.responses[1].position; i++ ) {
indent += '&nbsp;&nbsp;&nbsp;';
}

form.find( 'select#parent option:selected' ).after( '<option value="' + term.term_id + '">' + indent + term.name + '</option>' );
}

$('input:not([type="checkbox"]):not([type="radio"]):not([type="button"]):not([type="submit"]):not([type="reset"]):visible, textarea:visible', form).val('');
updateDisplayingNum( res.responses[0].supplemental.total );

$( 'input:not([type="checkbox"]):not([type="radio"]):not([type="button"]):not([type="submit"]):not([type="reset"]):visible, textarea:visible', form ).val( '' );
});

return false;
Expand Down
8 changes: 6 additions & 2 deletions src/wp-admin/includes/ajax-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -805,9 +805,10 @@ function wp_ajax_delete_tag() {
}

if ( wp_delete_term( $tag_id, $taxonomy ) ) {
wp_die( 1 );
$total = wp_count_terms( array( 'taxonomy' => $taxonomy ) );
wp_send_json_success( array( 'total' => (int) $total ) );
} else {
wp_die( 0 );
wp_send_json_error();
}
}

Expand Down Expand Up @@ -1153,6 +1154,8 @@ function wp_ajax_add_tag() {
$message = $messages['_item'][1];
}

$total = wp_count_terms( array( 'taxonomy' => $taxonomy ) );

$response->add(
array(
'what' => 'taxonomy',
Expand All @@ -1161,6 +1164,7 @@ function wp_ajax_add_tag() {
'parents' => $parents,
'noparents' => $no_parents,
'notice' => $message,
'total' => (int) $total,
),
)
);
Expand Down
35 changes: 35 additions & 0 deletions tests/phpunit/tests/ajax/wpAjaxAddTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,41 @@ public function test_adding_existing_category_should_error() {
$this->assertSame( $expected, (string) $this->get_xml_response_taxonomy()->wp_error );
}

/**
* Tests that the add tag AJAX response includes the total term count.
*
* @ticket 50082
*
* @covers ::wp_ajax_add_tag
* @covers ::wp_count_terms
*/
public function test_add_tag_returns_total_count() {
$this->_setRole( 'administrator' );

wp_insert_term( 'existing-tag', 'post_tag' );

$_POST = array(
'taxonomy' => 'post_tag',
'post_type' => 'post',
'screen' => 'edit-post_tag',
'action' => 'add-tag',
'tag-name' => 'new-tag',
'_wpnonce_add-tag' => wp_create_nonce( 'add-tag' ),
);

try {
$this->_handleAjax( 'add-tag' );
} catch ( WPAjaxDieContinueException $e ) {
unset( $e );
}

$xml = simplexml_load_string( $this->_last_response, 'SimpleXMLElement', LIBXML_NOCDATA );
$total = (int) $xml->response->taxonomy->supplemental->total;

// Two terms now exist: 'existing-tag' and 'new-tag'.
$this->assertSame( 2, $total );
}

/**
* Helper method to get the taxonomy's response or error.
*
Expand Down
76 changes: 76 additions & 0 deletions tests/phpunit/tests/ajax/wpAjaxDeleteTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

/**
* Admin ajax functions to be tested.
*/
require_once ABSPATH . 'wp-admin/includes/ajax-actions.php';

/**
* Class for testing ajax delete tag functionality.
*
* @group ajax
*
* @covers ::wp_ajax_delete_tag
*/
class Tests_Ajax_wpAjaxDeleteTag extends WP_Ajax_UnitTestCase {

/**
* Tests that deleting a tag returns JSON success with updated total count.
*
* @ticket 50082
*
* @covers ::wp_ajax_delete_tag
* @covers ::wp_count_terms
*/
public function test_delete_tag_returns_json_success_with_total() {
$this->_setRole( 'administrator' );

$term = wp_insert_term( 'tag-to-delete', 'post_tag' );
wp_insert_term( 'tag-to-keep', 'post_tag' );

$_POST = array(
'action' => 'delete-tag',
'tag_ID' => $term['term_id'],
'taxonomy' => 'post_tag',
'_wpnonce' => wp_create_nonce( 'delete-tag_' . $term['term_id'] ),
);

try {
$this->_handleAjax( 'delete-tag' );
} catch ( WPAjaxDieContinueException $e ) {
unset( $e );
}

$response = json_decode( $this->_last_response, true );

$this->assertTrue( $response['success'] );
// One term remains after deletion.
$this->assertSame( 1, $response['data']['total'] );
}

/**
* Tests that deleting a tag without permission returns -1.
*
* @ticket 50082
*
* @covers ::wp_ajax_delete_tag
*/
public function test_delete_tag_without_capability_should_error() {
$this->_setRole( 'subscriber' );

$term = self::factory()->term->create_and_get(
array( 'taxonomy' => 'post_tag' )
);

$_POST = array(
'action' => 'delete-tag',
'tag_ID' => $term->term_id,
'taxonomy' => 'post_tag',
'_wpnonce' => wp_create_nonce( 'delete-tag_' . $term->term_id ),
);

$this->expectException( 'WPAjaxDieStopException' );
$this->expectExceptionMessage( '-1' );
$this->_handleAjax( 'delete-tag' );
}
}
Loading