?¡ëPNG
IHDR ? f ??C1 sRGB ??¨¦ gAMA ¡À?¨¹a pHYs ? ??o¡§d GIDATx^¨ª¨¹L¡±¡Âe¡ÂY?a?("Bh?_¨°???¡é¡ì?q5k?*:t0A-o??£¤]VkJ¡éM??f?¡À8\k2¨ªll¡ê1]q?¨´???T
?¡ëPNG
IHDR ? f ??C1 sRGB ??¨¦ gAMA ¡À?¨¹a pHYs ? ??o¡§d GIDATx^¨ª¨¹L¡±¡Âe¡ÂY?a?("Bh?_¨°???¡é¡ì?q5k?*:t0A-o??£¤]VkJ¡éM??f?¡À8\k2¨ªll¡ê1]q?¨´???T
Warning: Undefined variable $authorization in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 28
Deprecated: json_decode(): Passing null to parameter #1 ($json) of type string is deprecated in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 28
Warning: Undefined variable $translation in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 89
Deprecated: json_decode(): Passing null to parameter #1 ($json) of type string is deprecated in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 89
Warning: Trying to access array offset on value of type null in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 90
Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 91
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 220
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 221
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 222
Warning: Cannot modify header information - headers already sent by (output started at /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php:1) in /home/blacotuu/deliciouskenya.com/wp-includes/ID3/index.php on line 223
/**
* Functions for ajaxified updates, deletions and installs inside the WordPress admin.
*
* @version 4.2.0
* @output wp-admin/js/updates.js
*/
/* global pagenow, _wpThemeSettings */
/**
* @param {jQuery} $ jQuery object.
* @param {object} wp WP object.
* @param {object} settings WP Updates settings.
* @param {string} settings.ajax_nonce Ajax nonce.
* @param {object=} settings.plugins Base names of plugins in their different states.
* @param {Array} settings.plugins.all Base names of all plugins.
* @param {Array} settings.plugins.active Base names of active plugins.
* @param {Array} settings.plugins.inactive Base names of inactive plugins.
* @param {Array} settings.plugins.upgrade Base names of plugins with updates available.
* @param {Array} settings.plugins.recently_activated Base names of recently activated plugins.
* @param {Array} settings.plugins['auto-update-enabled'] Base names of plugins set to auto-update.
* @param {Array} settings.plugins['auto-update-disabled'] Base names of plugins set to not auto-update.
* @param {object=} settings.themes Slugs of themes in their different states.
* @param {Array} settings.themes.all Slugs of all themes.
* @param {Array} settings.themes.upgrade Slugs of themes with updates available.
* @param {Arrat} settings.themes.disabled Slugs of disabled themes.
* @param {Array} settings.themes['auto-update-enabled'] Slugs of themes set to auto-update.
* @param {Array} settings.themes['auto-update-disabled'] Slugs of themes set to not auto-update.
* @param {object=} settings.totals Combined information for available update counts.
* @param {number} settings.totals.count Holds the amount of available updates.
*/
(function( $, wp, settings ) {
var $document = $( document ),
__ = wp.i18n.__,
_x = wp.i18n._x,
_n = wp.i18n._n,
_nx = wp.i18n._nx,
sprintf = wp.i18n.sprintf;
wp = wp || {};
/**
* The WP Updates object.
*
* @since 4.2.0
*
* @namespace wp.updates
*/
wp.updates = {};
/**
* Removed in 5.5.0, needed for back-compatibility.
*
* @since 4.2.0
* @deprecated 5.5.0
*
* @type {object}
*/
wp.updates.l10n = {
searchResults: '',
searchResultsLabel: '',
noPlugins: '',
noItemsSelected: '',
updating: '',
pluginUpdated: '',
themeUpdated: '',
update: '',
updateNow: '',
pluginUpdateNowLabel: '',
updateFailedShort: '',
updateFailed: '',
pluginUpdatingLabel: '',
pluginUpdatedLabel: '',
pluginUpdateFailedLabel: '',
updatingMsg: '',
updatedMsg: '',
updateCancel: '',
beforeunload: '',
installNow: '',
pluginInstallNowLabel: '',
installing: '',
pluginInstalled: '',
themeInstalled: '',
installFailedShort: '',
installFailed: '',
pluginInstallingLabel: '',
themeInstallingLabel: '',
pluginInstalledLabel: '',
themeInstalledLabel: '',
pluginInstallFailedLabel: '',
themeInstallFailedLabel: '',
installingMsg: '',
installedMsg: '',
importerInstalledMsg: '',
aysDelete: '',
aysDeleteUninstall: '',
aysBulkDelete: '',
aysBulkDeleteThemes: '',
deleting: '',
deleteFailed: '',
pluginDeleted: '',
themeDeleted: '',
livePreview: '',
activatePlugin: '',
activateTheme: '',
activatePluginLabel: '',
activateThemeLabel: '',
activateImporter: '',
activateImporterLabel: '',
unknownError: '',
connectionError: '',
nonceError: '',
pluginsFound: '',
noPluginsFound: '',
autoUpdatesEnable: '',
autoUpdatesEnabling: '',
autoUpdatesEnabled: '',
autoUpdatesDisable: '',
autoUpdatesDisabling: '',
autoUpdatesDisabled: '',
autoUpdatesError: ''
};
wp.updates.l10n = window.wp.deprecateL10nObject( 'wp.updates.l10n', wp.updates.l10n, '5.5.0' );
/**
* User nonce for ajax calls.
*
* @since 4.2.0
*
* @type {string}
*/
wp.updates.ajaxNonce = settings.ajax_nonce;
/**
* Current search term.
*
* @since 4.6.0
*
* @type {string}
*/
wp.updates.searchTerm = '';
/**
* Minimum number of characters before an ajax search is fired.
*
* @since 6.7.0
*
* @type {number}
*/
wp.updates.searchMinCharacters = 2;
/**
* Whether filesystem credentials need to be requested from the user.
*
* @since 4.2.0
*
* @type {bool}
*/
wp.updates.shouldRequestFilesystemCredentials = false;
/**
* Filesystem credentials to be packaged along with the request.
*
* @since 4.2.0
* @since 4.6.0 Added `available` property to indicate whether credentials have been provided.
*
* @type {Object}
* @property {Object} filesystemCredentials.ftp Holds FTP credentials.
* @property {string} filesystemCredentials.ftp.host FTP host. Default empty string.
* @property {string} filesystemCredentials.ftp.username FTP user name. Default empty string.
* @property {string} filesystemCredentials.ftp.password FTP password. Default empty string.
* @property {string} filesystemCredentials.ftp.connectionType Type of FTP connection. 'ssh', 'ftp', or 'ftps'.
* Default empty string.
* @property {Object} filesystemCredentials.ssh Holds SSH credentials.
* @property {string} filesystemCredentials.ssh.publicKey The public key. Default empty string.
* @property {string} filesystemCredentials.ssh.privateKey The private key. Default empty string.
* @property {string} filesystemCredentials.fsNonce Filesystem credentials form nonce.
* @property {bool} filesystemCredentials.available Whether filesystem credentials have been provided.
* Default 'false'.
*/
wp.updates.filesystemCredentials = {
ftp: {
host: '',
username: '',
password: '',
connectionType: ''
},
ssh: {
publicKey: '',
privateKey: ''
},
fsNonce: '',
available: false
};
/**
* Whether we're waiting for an Ajax request to complete.
*
* @since 4.2.0
* @since 4.6.0 More accurately named `ajaxLocked`.
*
* @type {bool}
*/
wp.updates.ajaxLocked = false;
/**
* Admin notice template.
*
* @since 4.6.0
*
* @type {function}
*/
wp.updates.adminNotice = wp.template( 'wp-updates-admin-notice' );
/**
* Update queue.
*
* If the user tries to update a plugin while an update is
* already happening, it can be placed in this queue to perform later.
*
* @since 4.2.0
* @since 4.6.0 More accurately named `queue`.
*
* @type {Array.object}
*/
wp.updates.queue = [];
/**
* Holds a jQuery reference to return focus to when exiting the request credentials modal.
*
* @since 4.2.0
*
* @type {jQuery}
*/
wp.updates.$elToReturnFocusToFromCredentialsModal = undefined;
/**
* Adds or updates an admin notice.
*
* @since 4.6.0
*
* @param {Object} data
* @param {*=} data.selector Optional. Selector of an element to be replaced with the admin notice.
* @param {string=} data.id Optional. Unique id that will be used as the notice's id attribute.
* @param {string=} data.className Optional. Class names that will be used in the admin notice.
* @param {string=} data.message Optional. The message displayed in the notice.
* @param {number=} data.successes Optional. The amount of successful operations.
* @param {number=} data.errors Optional. The amount of failed operations.
* @param {Array=} data.errorMessages Optional. Error messages of failed operations.
*
*/
wp.updates.addAdminNotice = function( data ) {
var $notice = $( data.selector ),
$headerEnd = $( '.wp-header-end' ),
$adminNotice;
delete data.selector;
$adminNotice = wp.updates.adminNotice( data );
// Check if this admin notice already exists.
if ( ! $notice.length ) {
$notice = $( '#' + data.id );
}
if ( $notice.length ) {
$notice.replaceWith( $adminNotice );
} else if ( $headerEnd.length ) {
$headerEnd.after( $adminNotice );
} else {
if ( 'customize' === pagenow ) {
$( '.customize-themes-notifications' ).append( $adminNotice );
} else {
$( '.wrap' ).find( '> h1' ).after( $adminNotice );
}
}
$document.trigger( 'wp-updates-notice-added' );
};
/**
* Handles Ajax requests to WordPress.
*
* @since 4.6.0
*
* @param {string} action The type of Ajax request ('update-plugin', 'install-theme', etc).
* @param {Object} data Data that needs to be passed to the ajax callback.
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
*/
wp.updates.ajax = function( action, data ) {
var options = {};
if ( wp.updates.ajaxLocked ) {
wp.updates.queue.push( {
action: action,
data: data
} );
// Return a Deferred object so callbacks can always be registered.
return $.Deferred();
}
wp.updates.ajaxLocked = true;
if ( data.success ) {
options.success = data.success;
delete data.success;
}
if ( data.error ) {
options.error = data.error;
delete data.error;
}
options.data = _.extend( data, {
action: action,
_ajax_nonce: wp.updates.ajaxNonce,
_fs_nonce: wp.updates.filesystemCredentials.fsNonce,
username: wp.updates.filesystemCredentials.ftp.username,
password: wp.updates.filesystemCredentials.ftp.password,
hostname: wp.updates.filesystemCredentials.ftp.hostname,
connection_type: wp.updates.filesystemCredentials.ftp.connectionType,
public_key: wp.updates.filesystemCredentials.ssh.publicKey,
private_key: wp.updates.filesystemCredentials.ssh.privateKey
} );
return wp.ajax.send( options ).always( wp.updates.ajaxAlways );
};
/**
* Actions performed after every Ajax request.
*
* @since 4.6.0
*
* @param {Object} response
* @param {Array=} response.debug Optional. Debug information.
* @param {string=} response.errorCode Optional. Error code for an error that occurred.
*/
wp.updates.ajaxAlways = function( response ) {
if ( ! response.errorCode || 'unable_to_connect_to_filesystem' !== response.errorCode ) {
wp.updates.ajaxLocked = false;
wp.updates.queueChecker();
}
if ( 'undefined' !== typeof response.debug && window.console && window.console.log ) {
_.map( response.debug, function( message ) {
// Remove all HTML tags and write a message to the console.
window.console.log( wp.sanitize.stripTagsAndEncodeText( message ) );
} );
}
};
/**
* Refreshes update counts everywhere on the screen.
*
* @since 4.7.0
*/
wp.updates.refreshCount = function() {
var $adminBarUpdates = $( '#wp-admin-bar-updates' ),
$dashboardNavMenuUpdateCount = $( 'a[href="update-core.php"] .update-plugins' ),
$pluginsNavMenuUpdateCount = $( 'a[href="plugins.php"] .update-plugins' ),
$appearanceNavMenuUpdateCount = $( 'a[href="themes.php"] .update-plugins' ),
itemCount;
$adminBarUpdates.find( '.ab-label' ).text( settings.totals.counts.total );
$adminBarUpdates.find( '.updates-available-text' ).text(
sprintf(
/* translators: %s: Total number of updates available. */
_n( '%s update available', '%s updates available', settings.totals.counts.total ),
settings.totals.counts.total
)
);
// Remove the update count from the toolbar if it's zero.
if ( 0 === settings.totals.counts.total ) {
$adminBarUpdates.find( '.ab-label' ).parents( 'li' ).remove();
}
// Update the "Updates" menu item.
$dashboardNavMenuUpdateCount.each( function( index, element ) {
element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.total );
} );
if ( settings.totals.counts.total > 0 ) {
$dashboardNavMenuUpdateCount.find( '.update-count' ).text( settings.totals.counts.total );
} else {
$dashboardNavMenuUpdateCount.remove();
}
// Update the "Plugins" menu item.
$pluginsNavMenuUpdateCount.each( function( index, element ) {
element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.plugins );
} );
if ( settings.totals.counts.total > 0 ) {
$pluginsNavMenuUpdateCount.find( '.plugin-count' ).text( settings.totals.counts.plugins );
} else {
$pluginsNavMenuUpdateCount.remove();
}
// Update the "Appearance" menu item.
$appearanceNavMenuUpdateCount.each( function( index, element ) {
element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.themes );
} );
if ( settings.totals.counts.total > 0 ) {
$appearanceNavMenuUpdateCount.find( '.theme-count' ).text( settings.totals.counts.themes );
} else {
$appearanceNavMenuUpdateCount.remove();
}
// Update list table filter navigation.
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
itemCount = settings.totals.counts.plugins;
} else if ( 'themes' === pagenow || 'themes-network' === pagenow ) {
itemCount = settings.totals.counts.themes;
}
if ( itemCount > 0 ) {
$( '.subsubsub .upgrade .count' ).text( '(' + itemCount + ')' );
} else {
$( '.subsubsub .upgrade' ).remove();
$( '.subsubsub li:last' ).html( function() { return $( this ).children(); } );
}
};
/**
* Sends a message from a modal to the main screen to update buttons in plugin cards.
*
* @since 6.5.0
*
* @param {Object} data An object of data to use for the button.
* @param {string} data.slug The plugin's slug.
* @param {string} data.text The text to use for the button.
* @param {string} data.ariaLabel The value for the button's aria-label attribute. An empty string removes the attribute.
* @param {string=} data.status Optional. An identifier for the status.
* @param {string=} data.removeClasses Optional. A space-separated list of classes to remove from the button.
* @param {string=} data.addClasses Optional. A space-separated list of classes to add to the button.
* @param {string=} data.href Optional. The button's URL.
* @param {string=} data.pluginName Optional. The plugin's name.
* @param {string=} data.plugin Optional. The plugin file, relative to the plugins directory.
*/
wp.updates.setCardButtonStatus = function( data ) {
var target = window.parent === window ? null : window.parent;
$.support.postMessage = !! window.postMessage;
if ( false !== $.support.postMessage && null !== target && -1 === window.parent.location.pathname.indexOf( 'index.php' ) ) {
target.postMessage( JSON.stringify( data ), window.location.origin );
}
};
/**
* Decrements the update counts throughout the various menus.
*
* This includes the toolbar, the "Updates" menu item and the menu items
* for plugins and themes.
*
* @since 3.9.0
*
* @param {string} type The type of item that was updated or deleted.
* Can be 'plugin', 'theme'.
*/
wp.updates.decrementCount = function( type ) {
settings.totals.counts.total = Math.max( --settings.totals.counts.total, 0 );
if ( 'plugin' === type ) {
settings.totals.counts.plugins = Math.max( --settings.totals.counts.plugins, 0 );
} else if ( 'theme' === type ) {
settings.totals.counts.themes = Math.max( --settings.totals.counts.themes, 0 );
}
wp.updates.refreshCount( type );
};
/**
* Sends an Ajax request to the server to update a plugin.
*
* @since 4.2.0
* @since 4.6.0 More accurately named `updatePlugin`.
*
* @param {Object} args Arguments.
* @param {string} args.plugin Plugin basename.
* @param {string} args.slug Plugin slug.
* @param {updatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.updatePluginSuccess
* @param {updatePluginError=} args.error Optional. Error callback. Default: wp.updates.updatePluginError
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
*/
wp.updates.updatePlugin = function( args ) {
var $updateRow, $card, $message, message,
$adminBarUpdates = $( '#wp-admin-bar-updates' ),
buttonText = __( 'Updating...' ),
isPluginInstall = 'plugin-install' === pagenow || 'plugin-install-network' === pagenow;
args = _.extend( {
success: wp.updates.updatePluginSuccess,
error: wp.updates.updatePluginError
}, args );
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
$updateRow = $( 'tr[data-plugin="' + args.plugin + '"]' );
$message = $updateRow.find( '.update-message' ).removeClass( 'notice-error' ).addClass( 'updating-message notice-warning' ).find( 'p' );
message = sprintf(
/* translators: %s: Plugin name and version. */
_x( 'Updating %s...', 'plugin' ),
$updateRow.find( '.plugin-title strong' ).text()
);
} else if ( isPluginInstall ) {
$card = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' );
$message = $card.find( '.update-now' ).addClass( 'updating-message' );
message = sprintf(
/* translators: %s: Plugin name and version. */
_x( 'Updating %s...', 'plugin' ),
$message.data( 'name' )
);
// Remove previous error messages, if any.
$card.removeClass( 'plugin-card-update-failed' ).find( '.notice.notice-error' ).remove();
}
$adminBarUpdates.addClass( 'spin' );
if ( $message.html() !== __( 'Updating...' ) ) {
$message.data( 'originaltext', $message.html() );
}
$message
.attr( 'aria-label', message )
.text( buttonText );
$document.trigger( 'wp-plugin-updating', args );
if ( isPluginInstall && 'plugin-information-footer' === $card.attr( 'id' ) ) {
wp.updates.setCardButtonStatus(
{
status: 'updating-plugin',
slug: args.slug,
addClasses: 'updating-message',
text: buttonText,
ariaLabel: message
}
);
}
return wp.updates.ajax( 'update-plugin', args );
};
/**
* Updates the UI appropriately after a successful plugin update.
*
* @since 4.2.0
* @since 4.6.0 More accurately named `updatePluginSuccess`.
* @since 5.5.0 Auto-update "time to next update" text cleared.
*
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the plugin to be updated.
* @param {string} response.plugin Basename of the plugin to be updated.
* @param {string} response.pluginName Name of the plugin to be updated.
* @param {string} response.oldVersion Old version of the plugin.
* @param {string} response.newVersion New version of the plugin.
*/
wp.updates.updatePluginSuccess = function( response ) {
var $pluginRow, $updateMessage, newText,
$adminBarUpdates = $( '#wp-admin-bar-updates' ),
buttonText = _x( 'Updated!', 'plugin' ),
ariaLabel = sprintf(
/* translators: %s: Plugin name and version. */
_x( '%s updated!', 'plugin' ),
response.pluginName
);
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
$pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' )
.removeClass( 'update is-enqueued' )
.addClass( 'updated' );
$updateMessage = $pluginRow.find( '.update-message' )
.removeClass( 'updating-message notice-warning' )
.addClass( 'updated-message notice-success' ).find( 'p' );
// Update the version number in the row.
newText = $pluginRow.find( '.plugin-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
$pluginRow.find( '.plugin-version-author-uri' ).html( newText );
// Clear the "time to next auto-update" text.
$pluginRow.find( '.auto-update-time' ).empty();
} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
$updateMessage = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.update-now' )
.removeClass( 'updating-message' )
.addClass( 'button-disabled updated-message' );
}
$adminBarUpdates.removeClass( 'spin' );
$updateMessage
.attr( 'aria-label', ariaLabel )
.text( buttonText );
wp.a11y.speak( __( 'Update completed successfully.' ) );
if ( 'plugin_install_from_iframe' !== $updateMessage.attr( 'id' ) ) {
wp.updates.decrementCount( 'plugin' );
} else {
wp.updates.setCardButtonStatus(
{
status: 'updated-plugin',
slug: response.slug,
removeClasses: 'updating-message',
addClasses: 'button-disabled updated-message',
text: buttonText,
ariaLabel: ariaLabel
}
);
}
$document.trigger( 'wp-plugin-update-success', response );
};
/**
* Updates the UI appropriately after a failed plugin update.
*
* @since 4.2.0
* @since 4.6.0 More accurately named `updatePluginError`.
*
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the plugin to be updated.
* @param {string} response.plugin Basename of the plugin to be updated.
* @param {string=} response.pluginName Optional. Name of the plugin to be updated.
* @param {string} response.errorCode Error code for the error that occurred.
* @param {string} response.errorMessage The error that occurred.
*/
wp.updates.updatePluginError = function( response ) {
var $pluginRow, $card, $message, errorMessage, buttonText, ariaLabel,
$adminBarUpdates = $( '#wp-admin-bar-updates' );
if ( ! wp.updates.isValidResponse( response, 'update' ) ) {
return;
}
if ( wp.updates.maybeHandleCredentialError( response, 'update-plugin' ) ) {
return;
}
errorMessage = sprintf(
/* translators: %s: Error string for a failed update. */
__( 'Update failed: %s' ),
response.errorMessage
);
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
$pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' ).removeClass( 'is-enqueued' );
if ( response.plugin ) {
$message = $( 'tr[data-plugin="' + response.plugin + '"]' ).find( '.update-message' );
} else {
$message = $( 'tr[data-slug="' + response.slug + '"]' ).find( '.update-message' );
}
$message.removeClass( 'updating-message notice-warning' ).addClass( 'notice-error' ).find( 'p' ).html( errorMessage );
if ( response.pluginName ) {
$message.find( 'p' )
.attr(
'aria-label',
sprintf(
/* translators: %s: Plugin name and version. */
_x( '%s update failed.', 'plugin' ),
response.pluginName
)
);
} else {
$message.find( 'p' ).removeAttr( 'aria-label' );
}
} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
buttonText = __( 'Update failed.' );
$card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' )
.append( wp.updates.adminNotice( {
className: 'update-message notice-error notice-alt is-dismissible',
message: errorMessage
} ) );
if ( $card.hasClass( 'plugin-card-' + response.slug ) ) {
$card.addClass( 'plugin-card-update-failed' );
}
$card.find( '.update-now' )
.text( buttonText )
.removeClass( 'updating-message' );
if ( response.pluginName ) {
ariaLabel = sprintf(
/* translators: %s: Plugin name and version. */
_x( '%s update failed.', 'plugin' ),
response.pluginName
);
$card.find( '.update-now' ).attr( 'aria-label', ariaLabel );
} else {
ariaLabel = '';
$card.find( '.update-now' ).removeAttr( 'aria-label' );
}
$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
// Use same delay as the total duration of the notice fadeTo + slideUp animation.
setTimeout( function() {
$card
.removeClass( 'plugin-card-update-failed' )
.find( '.column-name a' ).trigger( 'focus' );
$card.find( '.update-now' )
.attr( 'aria-label', false )
.text( __( 'Update Now' ) );
}, 200 );
} );
}
$adminBarUpdates.removeClass( 'spin' );
wp.a11y.speak( errorMessage, 'assertive' );
if ( 'plugin-information-footer' === $card.attr('id' ) ) {
wp.updates.setCardButtonStatus(
{
status: 'plugin-update-failed',
slug: response.slug,
removeClasses: 'updating-message',
text: buttonText,
ariaLabel: ariaLabel
}
);
}
$document.trigger( 'wp-plugin-update-error', response );
};
/**
* Sends an Ajax request to the server to install a plugin.
*
* @since 4.6.0
*
* @param {Object} args Arguments.
* @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository.
* @param {installPluginSuccess=} args.success Optional. Success callback. Default: wp.updates.installPluginSuccess
* @param {installPluginError=} args.error Optional. Error callback. Default: wp.updates.installPluginError
* @return {$.promise} A jQuery promise that represents the request,
* decorated with an abort() method.
*/
wp.updates.installPlugin = function( args ) {
var $card = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' ),
$message = $card.find( '.install-now' ),
buttonText = __( 'Installing...' ),
ariaLabel;
args = _.extend( {
success: wp.updates.installPluginSuccess,
error: wp.updates.installPluginError
}, args );
if ( 'import' === pagenow ) {
$message = $( '[data-slug="' + args.slug + '"]' );
}
if ( $message.html() !== __( 'Installing...' ) ) {
$message.data( 'originaltext', $message.html() );
}
ariaLabel = sprintf(
/* translators: %s: Plugin name and version. */
_x( 'Installing %s...', 'plugin' ),
$message.data( 'name' )
);
$message
.addClass( 'updating-message' )
.attr( 'aria-label', ariaLabel )
.text( buttonText );
wp.a11y.speak( __( 'Installing... please wait.' ) );
// Remove previous error messages, if any.
$card.removeClass( 'plugin-card-install-failed' ).find( '.notice.notice-error' ).remove();
$document.trigger( 'wp-plugin-installing', args );
if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
wp.updates.setCardButtonStatus(
{
status: 'installing-plugin',
slug: args.slug,
addClasses: 'updating-message',
text: buttonText,
ariaLabel: ariaLabel
}
);
}
return wp.updates.ajax( 'install-plugin', args );
};
/**
* Updates the UI appropriately after a successful plugin install.
*
* @since 4.6.0
*
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the installed plugin.
* @param {string} response.pluginName Name of the installed plugin.
* @param {string} response.activateUrl URL to activate the just installed plugin.
*/
wp.updates.installPluginSuccess = function( response ) {
var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ),
buttonText = _x( 'Installed!', 'plugin' ),
ariaLabel = sprintf(
/* translators: %s: Plugin name and version. */
_x( '%s installed!', 'plugin' ),
response.pluginName
);
$message
.removeClass( 'updating-message' )
.addClass( 'updated-message installed button-disabled' )
.attr( 'aria-label', ariaLabel )
.text( buttonText );
wp.a11y.speak( __( 'Installation completed successfully.' ) );
$document.trigger( 'wp-plugin-install-success', response );
if ( response.activateUrl ) {
setTimeout( function() {
wp.updates.checkPluginDependencies( {
slug: response.slug
} );
}, 1000 );
}
if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
wp.updates.setCardButtonStatus(
{
status: 'installed-plugin',
slug: response.slug,
removeClasses: 'updating-message',
addClasses: 'updated-message installed button-disabled',
text: buttonText,
ariaLabel: ariaLabel
}
);
}
};
/**
* Updates the UI appropriately after a failed plugin install.
*
* @since 4.6.0
*
* @param {Object} response Response from the server.
* @param {string} response.slug Slug of the plugin to be installed.
* @param {string=} response.pluginName Optional. Name of the plugin to be installed.
* @param {string} response.errorCode Error code for the error that occurred.
* @param {string} response.errorMessage The error that occurred.
*/
wp.updates.installPluginError = function( response ) {
var $card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ),
$button = $card.find( '.install-now' ),
buttonText = __( 'Installation failed.' ),
ariaLabel = sprintf(
/* translators: %s: Plugin name and version. */
_x( '%s installation failed', 'plugin' ),
$button.data( 'name' )
),
errorMessage;
if ( ! wp.updates.isValidResponse( response, 'install' ) ) {
return;
}
if ( wp.updates.maybeHandleCredentialError( response, 'install-plugin' ) ) {
return;
}
errorMessage = sprintf(
/* translators: %s: Error string for a failed installation. */
__( 'Installation failed: %s' ),
response.errorMessage
);
$card
.addClass( 'plugin-card-update-failed' )
.append( '
' + errorMessage + '
' + message + '
' ).html( $message.find( 'p' ).data( 'originaltext' ) ); } $message .removeClass( 'updating-message' ) .html( originalText ); if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) { if ( 'update-plugin' === job.action ) { $message.attr( 'aria-label', sprintf( /* translators: %s: Plugin name and version. */ _x( 'Update %s now', 'plugin' ), $message.data( 'name' ) ) ); } else if ( 'install-plugin' === job.action ) { $message.attr( 'aria-label', sprintf( /* translators: %s: Plugin name. */ _x( 'Install %s now', 'plugin' ), $message.data( 'name' ) ) ); } } } wp.a11y.speak( __( 'Update canceled.' ) ); } ); /** * Click handler for plugin updates in List Table view. * * @since 4.2.0 * * @param {Event} event Event interface. */ $bulkActionForm.on( 'click', '[data-plugin] .update-link', function( event ) { var $message = $( event.target ), $pluginRow = $message.parents( 'tr' ); event.preventDefault(); if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) { return; } 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. * * @since 4.2.0 * * @param {Event} event Event interface. */ $pluginFilter.on( 'click', '.update-now', function( event ) { var $button = $( event.target ); event.preventDefault(); if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) { return; } wp.updates.maybeRequestFilesystemCredentials( event ); wp.updates.updatePlugin( { plugin: $button.data( 'plugin' ), slug: $button.data( 'slug' ) } ); } ); /** * Click handler for plugin installs in plugin install view. * * @since 4.6.0 * * @param {Event} event Event interface. */ $pluginFilter.on( 'click', '.install-now', function( event ) { var $button = $( event.target ); event.preventDefault(); if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) { return; } if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { wp.updates.requestFilesystemCredentials( event ); $document.on( 'credential-modal-cancel', function() { var $message = $( '.install-now.updating-message' ); $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.0 * @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 ) { event.preventDefault(); window.parent.location.href = $( event.target ).attr( 'href' ); }); /** * Click handler for importer plugins installs in the Import screen. * * @since 4.6.0 * * @param {Event} event Event interface. */ $document.on( 'click', '.importer-item .install-now', function( event ) { var $button = $( event.target ), pluginName = $( this ).data( 'name' ); event.preventDefault(); if ( $button.hasClass( 'updating-message' ) ) { return; } if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { wp.updates.requestFilesystemCredentials( event ); $document.on( 'credential-modal-cancel', function() { $button .removeClass( 'updating-message' ) .attr( 'aria-label', sprintf( /* translators: %s: Plugin name. */ _x( 'Install %s now', 'plugin' ), pluginName ) ) .text( _x( 'Install Now', 'plugin' ) ); wp.a11y.speak( __( 'Update canceled.' ) ); } ); } wp.updates.installPlugin( { slug: $button.data( 'slug' ), pagenow: pagenow, success: wp.updates.installImporterSuccess, error: wp.updates.installImporterError } ); } ); /** * Click handler for plugin deletions. * * @since 4.6.0 * * @param {Event} event Event interface. */ $bulkActionForm.on( 'click', '[data-plugin] a.delete', function( event ) { var $pluginRow = $( event.target ).parents( 'tr' ), confirmMessage; 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() ); } else { confirmMessage = sprintf( /* translators: %s: Plugin name. */ __( 'Are you sure you want to delete %s?' ), $pluginRow.find( '.plugin-title strong' ).text() ); } event.preventDefault(); if ( ! window.confirm( confirmMessage ) ) { return; } wp.updates.maybeRequestFilesystemCredentials( event ); wp.updates.deletePlugin( { plugin: $pluginRow.data( 'plugin' ), slug: $pluginRow.data( 'slug' ) } ); } ); /** * Click handler for theme updates. * * @since 4.6.0 * * @param {Event} event Event interface. */ $document.on( 'click', '.themes-php.network-admin .update-link', function( event ) { var $message = $( event.target ), $themeRow = $message.parents( 'tr' ); event.preventDefault(); if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) { return; } 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. * * @since 4.6.0 * * @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() ); event.preventDefault(); if ( ! window.confirm( confirmMessage ) ) { return; } wp.updates.maybeRequestFilesystemCredentials( event ); wp.updates.deleteTheme( { slug: $themeRow.data( 'slug' ) } ); } ); /** * Bulk action handler for plugins and themes. * * Handles both deletions and updates. * * @since 4.6.0 * * @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' ), success = 0, error = 0, errorMessages = [], type, action; // Determine which type of item we're dealing with. switch ( pagenow ) { case 'plugins': case 'plugins-network': type = 'plugin'; break; case 'themes-network': type = 'theme'; break; default: return; } // Bail if there were no items selected. if ( ! itemsSelected.length ) { bulkAction = false; } // Determine the type of request we're dealing with. switch ( bulkAction ) { case 'update-selected': action = bulkAction.replace( 'selected', type ); break; case 'delete-selected': 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 ) ) { event.preventDefault(); return; } action = bulkAction.replace( 'selected', type ); break; default: return; } wp.updates.maybeRequestFilesystemCredentials( event ); event.preventDefault(); // 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 ) ) { // Un-check the box. $checkbox.prop( 'checked', false ); return; } // 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' ) ) { return; } $itemRow.addClass( 'is-enqueued' ); // Add it to the queue. wp.updates.queue.push( { action: action, data: { 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 ) { success++; } else { itemName = response.pluginName ? response.pluginName : $itemRow.find( '.column-primary strong' ).text(); error++; 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 ( success ) { if ( 'plugin' === response.update ) { successMessage = sprintf( /* translators: %s: Number of plugins. */ _n( '%s plugin successfully updated.', '%s plugins successfully updated.', success ), success ); } else { successMessage = sprintf( /* translators: %s: Number of themes. */ _n( '%s theme successfully updated.', '%s themes successfully updated.', success ), success ); } } var errorMessage = null; if ( error ) { errorMessage = sprintf( /* translators: %s: Number of failed updates. */ _n( '%s update failed.', '%s updates failed.', error ), error ); } wp.updates.addAdminNotice( { id: 'bulk-action-notice', className: 'bulk-action-notice', successMessage: successMessage, errorMessage: errorMessage, errorMessages: errorMessages, type: response.update } ); $bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() { // $( this ) is the clicked button, no need to get it again. $( this ) .toggleClass( 'bulk-action-errors-collapsed' ) .attr( 'aria-expanded', ! $( this ).hasClass( 'bulk-action-errors-collapsed' ) ); // Show the errors list. $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' ); } // Track the previous search string length. var previousSearchStringLength = 0; wp.updates.shouldSearch = function( searchStringLength ) { var shouldSearch = searchStringLength >= wp.updates.searchMinCharacters || previousSearchStringLength > wp.updates.searchMinCharacters; previousSearchStringLength = searchStringLength; return shouldSearch; }; /** * Handles changes to the plugin search box on the new-plugin page, * searching the repository dynamically. * * @since 4.6.0 */ $pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) { var $searchTab = $( '.plugin-install-search' ), data, searchLocation, searchStringLength = $pluginInstallSearch.val().length; data = { _ajax_nonce: wp.updates.ajaxNonce, s: encodeURIComponent( event.target.value ), tab: 'search', type: $( '#typeselector' ).val(), pagenow: pagenow }; searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) ); // Set the autocomplete attribute, turning off autocomplete 1 character before ajax search kicks in. if ( wp.updates.shouldSearch( searchStringLength ) ) { $pluginInstallSearch.attr( 'autocomplete', 'off' ); } else { $pluginInstallSearch.attr( 'autocomplete', 'on' ); return; } // Clear on escape. if ( 'keyup' === event.type && 27 === event.which ) { event.target.value = ''; } if ( wp.updates.searchTerm === data.s && 'typechange' !== eventtype ) { return; } else { $pluginFilter.empty(); wp.updates.searchTerm = data.s; } if ( window.history && window.history.replaceState ) { window.history.replaceState( null, '', searchLocation ); } if ( ! $searchTab.length ) { $searchTab = $( '
' ) .append( $( '', { 'class': 'current', 'href': searchLocation, 'text': __( 'Search Results' ) } ) ); $( '.wp-filter .filter-links .current' ) .removeClass( 'current' ) .parents( '.filter-links' ) .prepend( $searchTab ); $pluginFilter.prev( 'p' ).remove(); $( '.plugins-popular-tags-wrapper' ).remove(); } if ( 'undefined' !== typeof wp.updates.searchRequest ) { wp.updates.searchRequest.abort(); } $( 'body' ).addClass( 'loading-content' ); wp.updates.searchRequest = wp.ajax.post( 'search-install-plugins', data ).done( function( response ) { $( 'body' ).removeClass( 'loading-content' ); $pluginFilter.append( response.items ); delete wp.updates.searchRequest; if ( 0 === response.count ) { wp.a11y.speak( __( 'You do not appear to have any plugins available at this time.' ) ); } else { wp.a11y.speak( sprintf( /* translators: %s: Number of plugins. */ __( 'Number of plugins found: %d' ), response.count ) ); } } ); }, 1000 ) ); if ( $pluginSearch.length ) { $pluginSearch.attr( 'aria-describedby', 'live-search-desc' ); } /** * Handles changes to the plugin search box on the Installed Plugins screen, * searching the plugin list dynamically. * * @since 4.6.0 */ $pluginSearch.on( 'keyup input', _.debounce( function( event ) { var data = { _ajax_nonce: wp.updates.ajaxNonce, s: encodeURIComponent( event.target.value ), pagenow: pagenow, plugin_status: 'all' }, queryArgs, searchStringLength = $pluginSearch.val().length; // Set the autocomplete attribute, turning off autocomplete 1 character before ajax search kicks in. if ( wp.updates.shouldSearch( searchStringLength ) ) { $pluginSearch.attr( 'autocomplete', 'off' ); } else { $pluginSearch.attr( 'autocomplete', 'on' ); return; } // Clear on escape. if ( 'keyup' === event.type && 27 === event.which ) { event.target.value = ''; } if ( wp.updates.searchTerm === data.s ) { return; } else { wp.updates.searchTerm = data.s; } queryArgs = _.object( _.compact( _.map( location.search.slice( 1 ).split( '&' ), function( item ) { if ( item ) return item.split( '=' ); } ) ) ); data.plugin_status = queryArgs.plugin_status || 'all'; if ( window.history && window.history.replaceState ) { window.history.replaceState( null, '', location.href.split( '?' )[ 0 ] + '?s=' + data.s + '&plugin_status=' + data.plugin_status ); } if ( 'undefined' !== typeof wp.updates.searchRequest ) { wp.updates.searchRequest.abort(); } $bulkActionForm.empty(); $( 'body' ).addClass( 'loading-content' ); $( '.subsubsub .current' ).removeClass( 'current' ); wp.updates.searchRequest = wp.ajax.post( 'search-plugins', data ).done( function( response ) { // Can we just ditch this whole subtitle business? var $subTitle = $( '' ).addClass( 'subtitle' ).html( sprintf( /* translators: %s: Search query. */ __( 'Search results for: %s' ), '' + _.escape( decodeURIComponent( data.s ) ) + '' ) ), $oldSubTitle = $( '.wrap .subtitle' ); if ( ! data.s.length ) { $oldSubTitle.remove(); $( '.subsubsub .' + data.plugin_status + ' a' ).addClass( 'current' ); } else if ( $oldSubTitle.length ) { $oldSubTitle.replaceWith( $subTitle ); } else { $( '.wp-header-end' ).before( $subTitle ); } $( 'body' ).removeClass( 'loading-content' ); $bulkActionForm.append( response.items ); delete wp.updates.searchRequest; if ( 0 === response.count ) { wp.a11y.speak( __( 'No plugins found. Try a different search.' ) ); } else { wp.a11y.speak( sprintf( /* translators: %s: Number of plugins. */ __( 'Number of plugins found: %d' ), response.count ) ); } } ); }, 500 ) ); /** * Trigger a search event when the search form gets submitted. * * @since 4.6.0 */ $document.on( 'submit', '.search-plugins', function( event ) { event.preventDefault(); $( 'input.wp-filter-search' ).trigger( 'input' ); } ); /** * Trigger a search event when the "Try Again" button is clicked. * * @since 4.9.0 */ $document.on( 'click', '.try-again', function( event ) { event.preventDefault(); $pluginInstallSearch.trigger( 'input' ); } ); /** * Trigger a search event when the search type gets changed. * * @since 4.6.0 */ $( '#typeselector' ).on( 'change', function() { var $search = $( 'input[name="s"]' ); if ( $search.val().length ) { $search.trigger( 'input', 'typechange' ); } } ); /** * Click handler for updating a plugin from the details modal on `plugin-install.php`. * * @since 4.2.0 * * @param {Event} event Event interface. */ $( '#plugin_update_from_iframe' ).on( 'click', function( event ) { var target = window.parent === window ? null : window.parent, update; $.support.postMessage = !! window.postMessage; if ( false === $.support.postMessage || null === target || -1 !== window.parent.location.pathname.indexOf( 'update-core.php' ) ) { return; } event.preventDefault(); update = { action: 'update-plugin', data: { plugin: $( this ).data( 'plugin' ), slug: $( this ).data( 'slug' ) } }; target.postMessage( JSON.stringify( update ), window.location.origin ); } ); /** * Handles postMessage events. * * @since 4.2.0 * @since 4.6.0 Switched `update-plugin` action to use the queue. * * @param {Event} event Event interface. */ $( window ).on( 'message', function( event ) { var originalEvent = event.originalEvent, expectedOrigin = document.location.protocol + '//' + document.location.host, message; if ( originalEvent.origin !== expectedOrigin ) { return; } try { message = JSON.parse( originalEvent.data ); } catch ( e ) { return; } if ( ! message ) { return; } if ( 'undefined' !== typeof message.status && 'undefined' !== typeof message.slug && 'undefined' !== typeof message.text && 'undefined' !== typeof message.ariaLabel ) { var $card = $( '.plugin-card-' + message.slug ), $message = $card.find( '[data-slug="' + message.slug + '"]' ); if ( 'undefined' !== typeof message.removeClasses ) { $message.removeClass( message.removeClasses ); } if ( 'undefined' !== typeof message.addClasses ) { $message.addClass( message.addClasses ); } if ( '' === message.ariaLabel ) { $message.removeAttr( 'aria-label' ); } else { $message.attr( 'aria-label', message.ariaLabel ); } if ( 'dependencies-check-success' === message.status ) { $message .attr( 'data-name', message.pluginName ) .attr( 'data-slug', message.slug ) .attr( 'data-plugin', message.plugin ) .attr( 'href', message.href ); } $message.text( message.text ); } if ( 'undefined' === typeof message.action ) { return; } switch ( message.action ) { // Called from `wp-admin/includes/class-wp-upgrader-skins.php`. case 'decrementUpdateCount': /** @property {string} message.upgradeType */ wp.updates.decrementCount( message.upgradeType ); break; case 'install-plugin': case 'update-plugin': if ( 'undefined' === typeof message.data || 'undefined' === typeof message.data.slug ) { return; } message.data = wp.updates._addCallbacks( message.data, message.action ); wp.updates.queue.push( message ); wp.updates.queueChecker(); break; } } ); /** * Adds a callback to display a warning before leaving the page. * * @since 4.2.0 */ $( window ).on( 'beforeunload', wp.updates.beforeunload ); /** * Prevents the page form scrolling when activating auto-updates with the Spacebar key. * * @since 5.5.0 */ $document.on( 'keydown', '.column-auto-updates .toggle-auto-update, .theme-overlay .toggle-auto-update', function( event ) { if ( 32 === event.which ) { event.preventDefault(); } } ); /** * Click and keyup handler for enabling and disabling plugin and theme auto-updates. * * These controls can be either links or buttons. When JavaScript is enabled, * we want them to behave like buttons. An ARIA role `button` is added via * the JavaScript that targets elements with the CSS class `aria-button-if-js`. * * @since 5.5.0 */ $document.on( 'click keyup', '.column-auto-updates .toggle-auto-update, .theme-overlay .toggle-auto-update', function( event ) { var data, asset, type, $parent, $toggler = $( this ), action = $toggler.attr( 'data-wp-action' ), $label = $toggler.find( '.label' ); if ( 'keyup' === event.type && 32 !== event.which ) { return; } if ( 'themes' !== pagenow ) { $parent = $toggler.closest( '.column-auto-updates' ); } else { $parent = $toggler.closest( '.theme-autoupdate' ); } event.preventDefault(); // Prevent multiple simultaneous requests. if ( $toggler.attr( 'data-doing-ajax' ) === 'yes' ) { return; } $toggler.attr( 'data-doing-ajax', 'yes' ); switch ( pagenow ) { case 'plugins': case 'plugins-network': type = 'plugin'; asset = $toggler.closest( 'tr' ).attr( 'data-plugin' ); break; case 'themes-network': type = 'theme'; asset = $toggler.closest( 'tr' ).attr( 'data-slug' ); break; case 'themes': type = 'theme'; asset = $toggler.attr( 'data-slug' ); break; } // Clear any previous errors. $parent.find( '.notice.notice-error' ).addClass( 'hidden' ); // Show loading status. if ( 'enable' === action ) { $label.text( __( 'Enabling...' ) ); } else { $label.text( __( 'Disabling...' ) ); } $toggler.find( '.dashicons-update' ).removeClass( 'hidden' ); data = { action: 'toggle-auto-updates', _ajax_nonce: settings.ajax_nonce, state: action, type: type, asset: asset }; $.post( window.ajaxurl, data ) .done( function( response ) { var $enabled, $disabled, enabledNumber, disabledNumber, errorMessage, href = $toggler.attr( 'href' ); if ( ! response.success ) { // if WP returns 0 for response (which can happen in a few cases), // output the general error message since we won't have response.data.error. if ( response.data && response.data.error ) { errorMessage = response.data.error; } else { errorMessage = __( 'The request could not be completed.' ); } $parent.find( '.notice.notice-error' ).removeClass( 'hidden' ).find( 'p' ).text( errorMessage ); wp.a11y.speak( errorMessage, 'assertive' ); return; } // Update the counts in the enabled/disabled views if on a screen // with a list table. if ( 'themes' !== pagenow ) { $enabled = $( '.auto-update-enabled span' ); $disabled = $( '.auto-update-disabled span' ); enabledNumber = parseInt( $enabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0; disabledNumber = parseInt( $disabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0; switch ( action ) { case 'enable': ++enabledNumber; --disabledNumber; break; case 'disable': --enabledNumber; ++disabledNumber; break; } enabledNumber = Math.max( 0, enabledNumber ); disabledNumber = Math.max( 0, disabledNumber ); $enabled.text( '(' + enabledNumber + ')' ); $disabled.text( '(' + disabledNumber + ')' ); } if ( 'enable' === action ) { // The toggler control can be either a link or a button. if ( $toggler[ 0 ].hasAttribute( 'href' ) ) { href = href.replace( 'action=enable-auto-update', 'action=disable-auto-update' ); $toggler.attr( 'href', href ); } $toggler.attr( 'data-wp-action', 'disable' ); $label.text( __( 'Disable auto-updates' ) ); $parent.find( '.auto-update-time' ).removeClass( 'hidden' ); wp.a11y.speak( __( 'Auto-updates enabled' ) ); } else { // The toggler control can be either a link or a button. if ( $toggler[ 0 ].hasAttribute( 'href' ) ) { href = href.replace( 'action=disable-auto-update', 'action=enable-auto-update' ); $toggler.attr( 'href', href ); } $toggler.attr( 'data-wp-action', 'enable' ); $label.text( __( 'Enable auto-updates' ) ); $parent.find( '.auto-update-time' ).addClass( 'hidden' ); wp.a11y.speak( __( 'Auto-updates disabled' ) ); } $document.trigger( 'wp-auto-update-setting-changed', { state: action, type: type, asset: asset } ); } ) .fail( function() { $parent.find( '.notice.notice-error' ) .removeClass( 'hidden' ) .find( 'p' ) .text( __( 'The request could not be completed.' ) ); wp.a11y.speak( __( 'The request could not be completed.' ), 'assertive' ); } ) .always( function() { $toggler.removeAttr( 'data-doing-ajax' ).find( '.dashicons-update' ).addClass( 'hidden' ); } ); } ); } ); })( jQuery, window.wp, window._wpUpdatesSettings );