: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( wp.updates.maybeHandleCredentialError( response, 'delete-plugin' ) ) {
// Add a plugin update row if it doesn't exist yet.
if ( ! $pluginUpdateRow.length ) {
$plugin.addClass( 'update' ).after(
plugin: response.plugin || response.slug,
colspan: $( '#bulk-action-form' ).find( 'thead th:not(.hidden), thead td' ).length,
// Remove previous error messages, if any.
$pluginUpdateRow.find( '.notice-error' ).remove();
$pluginUpdateRow.find( '.plugin-update' ).append( noticeContent );
$document.trigger( 'wp-plugin-delete-error', response );
* Sends an Ajax request to the server to update a theme.
* @param {Object} args Arguments.
* @param {string} args.slug Theme stylesheet.
* @param {updateThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.updateThemeSuccess
* @param {updateThemeError=} args.error Optional. Error callback. Default: wp.updates.updateThemeError
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
wp.updates.updateTheme = function( args ) {
success: wp.updates.updateThemeSuccess,
error: wp.updates.updateThemeError
if ( 'themes-network' === pagenow ) {
$notice = $( '[data-slug="' + args.slug + '"]' ).find( '.update-message' ).removeClass( 'notice-error' ).addClass( 'updating-message notice-warning' ).find( 'p' );
} else if ( 'customize' === pagenow ) {
// Update the theme details UI.
$notice = $( '[data-slug="' + args.slug + '"].notice' ).removeClass( 'notice-large' );
$notice.find( 'h3' ).remove();
// Add the top-level UI, and update both.
$notice = $notice.add( $( '#customize-control-installed_theme_' + args.slug ).find( '.update-message' ) );
$notice = $notice.addClass( 'updating-message' ).find( 'p' );
$notice = $( '#update-theme' ).closest( '.notice' ).removeClass( 'notice-large' );
$notice.find( 'h3' ).remove();
$notice = $notice.add( $( '[data-slug="' + args.slug + '"]' ).find( '.update-message' ) );
$notice = $notice.addClass( 'updating-message' ).find( 'p' );
if ( $notice.html() !== __( 'Updating...' ) ) {
$notice.data( 'originaltext', $notice.html() );
wp.a11y.speak( __( 'Updating... please wait.' ) );
$notice.text( __( 'Updating...' ) );
$document.trigger( 'wp-theme-updating', args );
return wp.updates.ajax( 'update-theme', args );
* Updates the UI appropriately after a successful theme update.
* @since 5.5.0 Auto-update "time to next update" text cleared.
* @param {Object} response
* @param {string} response.slug Slug of the theme to be updated.
* @param {Object} response.theme Updated theme.
* @param {string} response.oldVersion Old version of the theme.
* @param {string} response.newVersion New version of the theme.
wp.updates.updateThemeSuccess = function( response ) {
var isModalOpen = $( 'body.modal-open' ).length,
$theme = $( '[data-slug="' + response.slug + '"]' ),
className: 'updated-message notice-success notice-alt',
message: _x( 'Updated!', 'theme' )
if ( 'customize' === pagenow ) {
$theme = $( '.updating-message' ).siblings( '.theme-name' );
// Update the version number in the row.
newText = $theme.html().replace( response.oldVersion, response.newVersion );
$notice = $( '.theme-info .notice' ).add( wp.customize.control( 'installed_theme_' + response.slug ).container.find( '.theme' ).find( '.update-message' ) );
} else if ( 'themes-network' === pagenow ) {
$notice = $theme.find( '.update-message' );
// Update the version number in the row.
newText = $theme.find( '.theme-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
$theme.find( '.theme-version-author-uri' ).html( newText );
// Clear the "time to next auto-update" text.
$theme.find( '.auto-update-time' ).empty();
$notice = $( '.theme-info .notice' ).add( $theme.find( '.update-message' ) );
// Focus on Customize button after updating.
$( '.load-customize:visible' ).trigger( 'focus' );
$( '.theme-info .theme-autoupdate' ).find( '.auto-update-time' ).empty();
$theme.find( '.load-customize' ).trigger( 'focus' );
wp.updates.addAdminNotice( _.extend( { selector: $notice }, updatedMessage ) );
wp.a11y.speak( __( 'Update completed successfully.' ) );
wp.updates.decrementCount( 'theme' );
$document.trigger( 'wp-theme-update-success', response );
// Show updated message after modal re-rendered.
if ( isModalOpen && 'customize' !== pagenow ) {
$( '.theme-info .theme-author' ).after( wp.updates.adminNotice( updatedMessage ) );
* Updates the UI appropriately after a failed theme update.
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the theme to be updated.
* @param {string} response.errorCode Error code for the error that occurred.
* @param {string} response.errorMessage The error that occurred.
wp.updates.updateThemeError = function( response ) {
var $theme = $( '[data-slug="' + response.slug + '"]' ),
/* translators: %s: Error string for a failed update. */
__( 'Update failed: %s' ),
if ( ! wp.updates.isValidResponse( response, 'update' ) ) {
if ( wp.updates.maybeHandleCredentialError( response, 'update-theme' ) ) {
if ( 'customize' === pagenow ) {
$theme = wp.customize.control( 'installed_theme_' + response.slug ).container.find( '.theme' );
if ( 'themes-network' === pagenow ) {
$notice = $theme.find( '.update-message ' );
$notice = $( '.theme-info .notice' ).add( $theme.find( '.notice' ) );
$( 'body.modal-open' ).length ? $( '.load-customize:visible' ).trigger( 'focus' ) : $theme.find( '.load-customize' ).trigger( 'focus');
wp.updates.addAdminNotice( {
className: 'update-message notice-error notice-alt is-dismissible',
wp.a11y.speak( errorMessage );
$document.trigger( 'wp-theme-update-error', response );
* Sends an Ajax request to the server to install a theme.
* @param {string} args.slug Theme stylesheet.
* @param {installThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.installThemeSuccess
* @param {installThemeError=} args.error Optional. Error callback. Default: wp.updates.installThemeError
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
wp.updates.installTheme = function( args ) {
var $message = $( '.theme-install[data-slug="' + args.slug + '"]' );
success: wp.updates.installThemeSuccess,
error: wp.updates.installThemeError
$message.addClass( 'updating-message' );
$message.parents( '.theme' ).addClass( 'focus' );
if ( $message.html() !== __( 'Installing...' ) ) {
$message.data( 'originaltext', $message.html() );
/* translators: %s: Theme name and version. */
_x( 'Installing %s...', 'theme' ),
.text( __( 'Installing...' ) );
wp.a11y.speak( __( 'Installing... please wait.' ) );
// Remove previous error messages, if any.
$( '.install-theme-info, [data-slug="' + args.slug + '"]' ).removeClass( 'theme-install-failed' ).find( '.notice.notice-error' ).remove();
$document.trigger( 'wp-theme-installing', args );
return wp.updates.ajax( 'install-theme', args );
* Updates the UI appropriately after a successful theme install.
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the theme to be installed.
* @param {string} response.customizeUrl URL to the Customizer for the just installed theme.
* @param {string} response.activateUrl URL to activate the just installed theme.
wp.updates.installThemeSuccess = function( response ) {
var $card = $( '.wp-full-overlay-header, [data-slug=' + response.slug + ']' ),
$document.trigger( 'wp-theme-install-success', response );
$message = $card.find( '.button-primary' )
.removeClass( 'updating-message' )
.addClass( 'updated-message disabled' )
/* translators: %s: Theme name and version. */
_x( '%s installed!', 'theme' ),
.text( _x( 'Installed!', 'theme' ) );
wp.a11y.speak( __( 'Installation completed successfully.' ) );
if ( response.activateUrl ) {
// Transform the 'Install' button into an 'Activate' button.
.attr( 'href', response.activateUrl )
.removeClass( 'theme-install updated-message disabled' )
if ( 'themes-network' === pagenow ) {
/* translators: %s: Theme name. */
_x( 'Network Activate %s', 'theme' ),
.text( __( 'Network Enable' ) );
/* translators: %s: Theme name. */
_x( 'Activate %s', 'theme' ),
.text( _x( 'Activate', 'theme' ) );
if ( response.customizeUrl ) {
// Transform the 'Preview' button into a 'Live Preview' button.
$message.siblings( '.preview' ).replaceWith( function () {
.attr( 'href', response.customizeUrl )
.addClass( 'button load-customize' )
.text( __( 'Live Preview' ) );
* Updates the UI appropriately after a failed theme install.
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the theme to be installed.
* @param {string} response.errorCode Error code for the error that occurred.
* @param {string} response.errorMessage The error that occurred.
wp.updates.installThemeError = function( response ) {
/* translators: %s: Error string for a failed installation. */
__( 'Installation failed: %s' ),
$message = wp.updates.adminNotice( {
className: 'update-message notice-error notice-alt',
if ( ! wp.updates.isValidResponse( response, 'install' ) ) {
if ( wp.updates.maybeHandleCredentialError( response, 'install-theme' ) ) {
if ( 'customize' === pagenow ) {
if ( $document.find( 'body' ).hasClass( 'modal-open' ) ) {
$button = $( '.theme-install[data-slug="' + response.slug + '"]' );
$card = $( '.theme-overlay .theme-info' ).prepend( $message );
$button = $( '.theme-install[data-slug="' + response.slug + '"]' );
$card = $button.closest( '.theme' ).addClass( 'theme-install-failed' ).append( $message );
wp.customize.notifications.remove( 'theme_installing' );
if ( $document.find( 'body' ).hasClass( 'full-overlay-active' ) ) {
$button = $( '.theme-install[data-slug="' + response.slug + '"]' );
$card = $( '.install-theme-info' ).prepend( $message );
$card = $( '[data-slug="' + response.slug + '"]' ).removeClass( 'focus' ).addClass( 'theme-install-failed' ).append( $message );
$button = $card.find( '.theme-install' );
.removeClass( 'updating-message' )
/* translators: %s: Theme name and version. */
_x( '%s installation failed', 'theme' ),
.text( __( 'Installation failed.' ) );
wp.a11y.speak( errorMessage, 'assertive' );
$document.trigger( 'wp-theme-install-error', response );
* Sends an Ajax request to the server to delete a theme.
* @param {string} args.slug Theme stylesheet.
* @param {deleteThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.deleteThemeSuccess
* @param {deleteThemeError=} args.error Optional. Error callback. Default: wp.updates.deleteThemeError
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
wp.updates.deleteTheme = function( args ) {
if ( 'themes' === pagenow ) {
$button = $( '.theme-actions .delete-theme' );
} else if ( 'themes-network' === pagenow ) {
$button = $( '[data-slug="' + args.slug + '"]' ).find( '.row-actions a.delete' );
success: wp.updates.deleteThemeSuccess,
error: wp.updates.deleteThemeError
if ( $button && $button.html() !== __( 'Deleting...' ) ) {
.data( 'originaltext', $button.html() )
.text( __( 'Deleting...' ) );
wp.a11y.speak( __( 'Deleting...' ) );
// Remove previous error messages, if any.
$( '.theme-info .update-message' ).remove();
$document.trigger( 'wp-theme-deleting', args );
return wp.updates.ajax( 'delete-theme', args );
* Updates the UI appropriately after a successful theme deletion.
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the theme that was deleted.
wp.updates.deleteThemeSuccess = function( response ) {
var $themeRows = $( '[data-slug="' + response.slug + '"]' );
if ( 'themes-network' === pagenow ) {
// Removes the theme and updates rows.
$themeRows.css( { backgroundColor: '#faafaa' } ).fadeOut( 350, function() {
var $views = $( '.subsubsub' ),
themes = settings.themes,
deletedRow = wp.template( 'item-deleted-row' );
if ( ! $themeRow.hasClass( 'plugin-update-tr' ) ) {
colspan: $( '#bulk-action-form' ).find( 'thead th:not(.hidden), thead td' ).length,
name: $themeRow.find( '.theme-title strong' ).text()
// Remove theme from update count.
if ( -1 !== _.indexOf( themes.upgrade, response.slug ) ) {
themes.upgrade = _.without( themes.upgrade, response.slug );
wp.updates.decrementCount( 'theme' );
if ( -1 !== _.indexOf( themes.disabled, response.slug ) ) {
themes.disabled = _.without( themes.disabled, response.slug );
if ( themes.disabled.length ) {
$views.find( '.disabled .count' ).text( '(' + themes.disabled.length + ')' );
$views.find( '.disabled' ).remove();
if ( -1 !== _.indexOf( themes['auto-update-enabled'], response.slug ) ) {
themes['auto-update-enabled'] = _.without( themes['auto-update-enabled'], response.slug );
if ( themes['auto-update-enabled'].length ) {
$views.find( '.auto-update-enabled .count' ).text( '(' + themes['auto-update-enabled'].length + ')' );
$views.find( '.auto-update-enabled' ).remove();
if ( -1 !== _.indexOf( themes['auto-update-disabled'], response.slug ) ) {
themes['auto-update-disabled'] = _.without( themes['auto-update-disabled'], response.slug );
if ( themes['auto-update-disabled'].length ) {
$views.find( '.auto-update-disabled .count' ).text( '(' + themes['auto-update-disabled'].length + ')' );
$views.find( '.auto-update-disabled' ).remove();
themes.all = _.without( themes.all, response.slug );
// There is always at least one theme available.
$views.find( '.all .count' ).text( '(' + themes.all.length + ')' );