: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( 'update-plugin' === job.action ) {
$message = $( 'tr[data-plugin="' + job.data.plugin + '"]' ).find( '.update-message' );
} else if ( 'delete-plugin' === job.action ) {
$message = $( '[data-plugin="' + job.data.plugin + '"]' ).find( '.row-actions a.delete' );
} else if ( 'themes' === pagenow || 'themes-network' === pagenow ) {
if ( 'update-theme' === job.action ) {
$message = $( '[data-slug="' + job.data.slug + '"]' ).find( '.update-message' );
} else if ( 'delete-theme' === job.action && 'themes-network' === pagenow ) {
$message = $( '[data-slug="' + job.data.slug + '"]' ).find( '.row-actions a.delete' );
} else if ( 'delete-theme' === job.action && 'themes' === pagenow ) {
$message = $( '.theme-actions .delete-theme' );
$message = $updatingMessage;
if ( $message && $message.hasClass( 'updating-message' ) ) {
originalText = $message.data( 'originaltext' );
if ( 'undefined' === typeof originalText ) {
originalText = $( '<p>' ).html( $message.find( 'p' ).data( 'originaltext' ) );
.removeClass( 'updating-message' )
if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
if ( 'update-plugin' === job.action ) {
/* translators: %s: Plugin name and version. */
_x( 'Update %s now', 'plugin' ),
} else if ( 'install-plugin' === job.action ) {
/* translators: %s: Plugin name. */
_x( 'Install %s now', 'plugin' ),
wp.a11y.speak( __( 'Update canceled.' ) );
* Click handler for plugin updates in List Table view.
* @param {Event} event Event interface.
$bulkActionForm.on( 'click', '[data-plugin] .update-link', function( event ) {
var $message = $( event.target ),
$pluginRow = $message.parents( 'tr' );
if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) {
wp.updates.maybeRequestFilesystemCredentials( event );
// Return the user to the input box of the plugin's table row after closing the modal.
wp.updates.$elToReturnFocusToFromCredentialsModal = $pluginRow.find( '.check-column input' );
wp.updates.updatePlugin( {
plugin: $pluginRow.data( 'plugin' ),
slug: $pluginRow.data( 'slug' )
* Click handler for plugin updates in plugin install view.
* @param {Event} event Event interface.
$pluginFilter.on( 'click', '.update-now', function( event ) {
var $button = $( event.target );
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
wp.updates.maybeRequestFilesystemCredentials( event );
wp.updates.updatePlugin( {
plugin: $button.data( 'plugin' ),
slug: $button.data( 'slug' )
* Click handler for plugin installs in plugin install view.
* @param {Event} event Event interface.
$pluginFilter.on( 'click', '.install-now', function( event ) {
var $button = $( event.target );
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) {
wp.updates.requestFilesystemCredentials( event );
$document.on( 'credential-modal-cancel', function() {
var $message = $( '.install-now.updating-message' );
.removeClass( 'updating-message' )
.text( _x( 'Install Now', 'plugin' ) );
wp.a11y.speak( __( 'Update canceled.' ) );
wp.updates.installPlugin( {
slug: $button.data( 'slug' )
* Click handler for plugin activations in plugin activation modal view.
* @since 6.5.4 Redirect the parent window to the activation URL.
* @param {Event} event Event interface.
$document.on( 'click', '#plugin-information-footer .activate-now', function( event ) {
window.parent.location.href = $( event.target ).attr( 'href' );
* Click handler for importer plugins installs in the Import screen.
* @param {Event} event Event interface.
$document.on( 'click', '.importer-item .install-now', function( event ) {
var $button = $( event.target ),
pluginName = $( this ).data( 'name' );
if ( $button.hasClass( 'updating-message' ) ) {
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) {
wp.updates.requestFilesystemCredentials( event );
$document.on( 'credential-modal-cancel', function() {
.removeClass( 'updating-message' )
/* translators: %s: Plugin name. */
_x( 'Install %s now', 'plugin' ),
.text( _x( 'Install Now', 'plugin' ) );
wp.a11y.speak( __( 'Update canceled.' ) );
wp.updates.installPlugin( {
slug: $button.data( 'slug' ),
success: wp.updates.installImporterSuccess,
error: wp.updates.installImporterError
* Click handler for plugin deletions.
* @param {Event} event Event interface.
$bulkActionForm.on( 'click', '[data-plugin] a.delete', function( event ) {
var $pluginRow = $( event.target ).parents( 'tr' ),
if ( $pluginRow.hasClass( 'is-uninstallable' ) ) {
confirmMessage = sprintf(
/* translators: %s: Plugin name. */
__( 'Are you sure you want to delete %s and its data?' ),
$pluginRow.find( '.plugin-title strong' ).text()
confirmMessage = sprintf(
/* translators: %s: Plugin name. */
__( 'Are you sure you want to delete %s?' ),
$pluginRow.find( '.plugin-title strong' ).text()
if ( ! window.confirm( confirmMessage ) ) {
wp.updates.maybeRequestFilesystemCredentials( event );
wp.updates.deletePlugin( {
plugin: $pluginRow.data( 'plugin' ),
slug: $pluginRow.data( 'slug' )
* Click handler for theme updates.
* @param {Event} event Event interface.
$document.on( 'click', '.themes-php.network-admin .update-link', function( event ) {
var $message = $( event.target ),
$themeRow = $message.parents( 'tr' );
if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) {
wp.updates.maybeRequestFilesystemCredentials( event );
// Return the user to the input box of the theme's table row after closing the modal.
wp.updates.$elToReturnFocusToFromCredentialsModal = $themeRow.find( '.check-column input' );
wp.updates.updateTheme( {
slug: $themeRow.data( 'slug' )
* Click handler for theme deletions.
* @param {Event} event Event interface.
$document.on( 'click', '.themes-php.network-admin a.delete', function( event ) {
var $themeRow = $( event.target ).parents( 'tr' ),
confirmMessage = sprintf(
/* translators: %s: Theme name. */
__( 'Are you sure you want to delete %s?' ),
$themeRow.find( '.theme-title strong' ).text()
if ( ! window.confirm( confirmMessage ) ) {
wp.updates.maybeRequestFilesystemCredentials( event );
wp.updates.deleteTheme( {
slug: $themeRow.data( 'slug' )
* Bulk action handler for plugins and themes.
* Handles both deletions and updates.
* @param {Event} event Event interface.
$bulkActionForm.on( 'click', '[type="submit"]:not([name="clear-recent-list"])', function( event ) {
var bulkAction = $( event.target ).siblings( 'select' ).val(),
itemsSelected = $bulkActionForm.find( 'input[name="checked[]"]:checked' ),
// Determine which type of item we're dealing with.
// Bail if there were no items selected.
if ( ! itemsSelected.length ) {
$( 'html, body' ).animate( { scrollTop: 0 } );
return wp.updates.addAdminNotice( {
className: 'notice-error is-dismissible',
message: __( 'Please select at least one item to perform this action on.' )
// Determine the type of request we're dealing with.
action = bulkAction.replace( 'selected', type );
var confirmMessage = 'plugin' === type ?
__( 'Are you sure you want to delete the selected plugins and their data?' ) :
__( 'Caution: These themes may be active on other sites in the network. Are you sure you want to proceed?' );
if ( ! window.confirm( confirmMessage ) ) {
action = bulkAction.replace( 'selected', type );
wp.updates.maybeRequestFilesystemCredentials( event );
// Un-check the bulk checkboxes.
$bulkActionForm.find( '.manage-column [type="checkbox"]' ).prop( 'checked', false );
$document.trigger( 'wp-' + type + '-bulk-' + bulkAction, itemsSelected );
// Find all the checkboxes which have been checked.
itemsSelected.each( function( index, element ) {
var $checkbox = $( element ),
$itemRow = $checkbox.parents( 'tr' );
// Only add update-able items to the update queue.
if ( 'update-selected' === bulkAction && ( ! $itemRow.hasClass( 'update' ) || $itemRow.find( 'notice-error' ).length ) ) {
$checkbox.prop( 'checked', false );
// Don't add items to the update queue again, even if the user clicks the update button several times.
if ( 'update-selected' === bulkAction && $itemRow.hasClass( 'is-enqueued' ) ) {
$itemRow.addClass( 'is-enqueued' );
plugin: $itemRow.data( 'plugin' ),
slug: $itemRow.data( 'slug' )
// Display bulk notification for updates of any kind.
$document.on( 'wp-plugin-update-success wp-plugin-update-error wp-theme-update-success wp-theme-update-error', function( event, response ) {
var $itemRow = $( '[data-slug="' + response.slug + '"]' ),
$bulkActionNotice, itemName;
if ( 'wp-' + response.update + '-update-success' === event.type ) {
itemName = response.pluginName ? response.pluginName : $itemRow.find( '.column-primary strong' ).text();
errorMessages.push( itemName + ': ' + response.errorMessage );
$itemRow.find( 'input[name="checked[]"]:checked' ).prop( 'checked', false );
wp.updates.adminNotice = wp.template( 'wp-bulk-updates-admin-notice' );
var successMessage = null;
if ( 'plugin' === response.update ) {
successMessage = sprintf(
/* translators: %s: Number of plugins. */
_n( '%s plugin successfully updated.', '%s plugins successfully updated.', success ),
successMessage = sprintf(
/* translators: %s: Number of themes. */
_n( '%s theme successfully updated.', '%s themes successfully updated.', success ),
/* translators: %s: Number of failed updates. */
_n( '%s update failed.', '%s updates failed.', error ),
wp.updates.addAdminNotice( {
id: 'bulk-action-notice',
className: 'bulk-action-notice',
successMessage: successMessage,
errorMessage: errorMessage,
errorMessages: errorMessages,
$bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() {
// $( this ) is the clicked button, no need to get it again.
.toggleClass( 'bulk-action-errors-collapsed' )
.attr( 'aria-expanded', ! $( this ).hasClass( 'bulk-action-errors-collapsed' ) );
$bulkActionNotice.find( '.bulk-action-errors' ).toggleClass( 'hidden' );
if ( error > 0 && ! wp.updates.queue.length ) {
$( 'html, body' ).animate( { scrollTop: 0 } );
// Reset admin notice template after #bulk-action-notice was added.
$document.on( 'wp-updates-notice-added', function() {
wp.updates.adminNotice = wp.template( 'wp-updates-admin-notice' );
// Check the queue, now that the event handlers have been added.
wp.updates.queueChecker();
if ( $pluginInstallSearch.length ) {
$pluginInstallSearch.attr( 'aria-describedby', 'live-search-desc' );
* Handles changes to the plugin search box on the new-plugin page,
* searching the repository dynamically.
$pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) {
var $searchTab = $( '.plugin-install-search' ), data, searchLocation;
_ajax_nonce: wp.updates.ajaxNonce,
s: encodeURIComponent( event.target.value ),
type: $( '#typeselector' ).val(),
searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) );
if ( 'keyup' === event.type && 27 === event.which ) {