[wp-trac] [WordPress Trac] #65191: deletePluginSuccess does not update counts for custom plugin_status groups
WordPress Trac
noreply at wordpress.org
Thu May 7 15:05:13 UTC 2026
#65191: deletePluginSuccess does not update counts for custom plugin_status groups
--------------------------+---------------------------------------
Reporter: andrew.p | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Plugins | Version:
Severity: minor | Keywords: needs-testing needs-patch
Focuses: |
--------------------------+---------------------------------------
#60495 added the `plugins_list_status_text` filter, so plugins can
register custom group tabs on `plugins.php` by adding entries to the array
passed through `plugins_list` and supplying a label through the new
filter.
The server side works. The count badge is right on initial load, and
`?plugin_status=<custom>` filters the list as expected.
The AJAX delete flow does not keep up. `wp.updates.deletePluginSuccess` in
`wp-admin/js/updates.js` only decrements counts for the hardcoded buckets
(`upgrade`, `inactive`, `active`, `recently_activated`). Anything added
through `plugins_list` is skipped, so the badge on the custom tab stays
stale until the page reloads.
== Steps to reproduce ==
1. Drop the snippet below into a must-use plugin to register a sample
group.
{{{
#!php
<?php
add_filter( 'plugins_list', function( $plugins ) {
if ( empty( $plugins['all'] ) ) {
return $plugins;
}
$plugins['demo_group'] = array_filter(
$plugins['all'],
static function ( $data, $file ) {
return str_starts_with( $file, 'a' );
},
ARRAY_FILTER_USE_BOTH
);
return $plugins;
} );
add_filter( 'plugins_list_status_text', function( $text, $count, $type ) {
return $type === 'demo_group' ? 'Demo Group' : $text;
}, 10, 3 );
}}}
2. Install two plugins whose folder starts with `a`, plus one that does
not.
3. Visit `wp-admin/plugins.php`. The "Demo Group (2)" tab shows the right
count.
4. Click the tab. Delete one of the listed plugins from the row actions.
5. The row fades out, but the tab still reads "(2)".
6. Reload the page. The tab now reads "(1)", matching what the server
returns.
The hardcoded tabs (`Active`, `Inactive`) decrement correctly in the same
flow.
== Cause ==
In `wp-admin/js/updates.js`, `deletePluginSuccess` checks four buckets and
stops:
{{{
#!js
if ( -1 !== _.indexOf( plugins.upgrade, response.plugin ) ) { ... }
if ( -1 !== _.indexOf( plugins.inactive, response.plugin ) ) { ... }
if ( -1 !== _.indexOf( plugins.active, response.plugin ) ) { ... }
if ( -1 !== _.indexOf( plugins.recently_activated, response.plugin ) ) {
... }
}}}
Other keys present in `plugins` are not iterated.
== Suggested approach ==
After the existing blocks, walk any remaining keys and apply the same
pattern. Hardcoded keys keep their explicit path, so existing sites see no
behavior change.
{{{
#!js
var knownKeys = [ 'all', 'search', 'upgrade', 'active', 'inactive',
'recently_activated', 'mustuse', 'dropins', 'paused',
'auto-update-enabled', 'auto-update-disabled' ];
_.each( _.keys( plugins ), function( key ) {
if ( -1 !== _.indexOf( knownKeys, key ) ) {
return;
}
if ( ! _.isArray( plugins[ key ] ) ) {
return;
}
if ( -1 === _.indexOf( plugins[ key ], response.plugin ) ) {
return;
}
plugins[ key ] = _.without( plugins[ key ], response.plugin );
var $tab = $views.find( '.' + key );
if ( plugins[ key ].length ) {
$tab.find( '.count' ).text( '(' + plugins[ key ].length +
')' );
} else {
$tab.remove();
}
} );
}}}
The activate, deactivate, and update success callbacks likely have the
same gap. Happy to roll those into one patch if reviewers want a single
sweep, otherwise this ticket can stay scoped to delete.
== Notes ==
`wp-plugin-delete-success` is already triggered as a jQuery event, so
individual plugins can shim this on the client. With #60495 turning custom
groups into a documented extension point, asking every consumer to ship
the same workaround does not feel right.
== Test plan ==
- Hardcoded tabs: delete still decrements `Active`, `Inactive`, and
`Update available` exactly as before.
- Custom group registered via `plugins_list`: the count drops on delete,
and the tab disappears when it reaches zero.
- Sites with no custom group: no change, no extra DOM lookups.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/65191>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list