Adds a new 'S3-Compatible Storage' provider that works with any
S3-API-compatible object storage service, including MinIO, Ceph,
Cloudflare R2, Backblaze B2, and others.
Changes:
- New provider class: classes/providers/storage/s3-compatible-provider.php
- Provider key: s3compatible
- Reads user-configured endpoint URL from settings
- Uses path-style URL access (required by most S3-compatible services)
- Supports credentials via AS3CF_S3COMPAT_ACCESS_KEY_ID /
AS3CF_S3COMPAT_SECRET_ACCESS_KEY wp-config.php constants
- Disables AWS-specific features (Block Public Access, Object Ownership)
- New provider SVG icons (s3compatible.svg, -link.svg, -round.svg)
- Registered provider in main plugin class with endpoint setting support
- Updated StorageProviderSubPage to show endpoint URL input for S3-compatible
- Built pro settings bundle with rollup (Svelte 4.2.19)
- Added package.json and updated rollup.config.mjs for pro-only builds
310 lines
7.8 KiB
JavaScript
310 lines
7.8 KiB
JavaScript
(function( $ ) {
|
|
|
|
/**
|
|
* The list table used on the current page.
|
|
* plugins.php : .wp-list-table.plugins
|
|
* update-core.php : #update-plugins-table
|
|
* @type {Object}
|
|
*/
|
|
const $listTable = $( '#update-plugins-table,.wp-list-table.plugins' );
|
|
|
|
/**
|
|
* Class representing a single plugin in the context of a list table of plugin updates.
|
|
*
|
|
* @param {object} data
|
|
* @param {Plugin|undefined} parent
|
|
* @constructor
|
|
*/
|
|
const Plugin = function( data, parent ) {
|
|
|
|
/**
|
|
* Data provided by the server.
|
|
* @type {Object}
|
|
*/
|
|
this.data = data;
|
|
|
|
/**
|
|
* Parent Plugin instance, if representing an add-on.
|
|
* @type {Plugin|undefined}
|
|
*/
|
|
this.parent = parent;
|
|
|
|
/**
|
|
* Object for the checkbox allowing the plugin to be submitted for update.
|
|
* @type {Object} jQuery
|
|
*/
|
|
this.$check = $listTable.find( '.check-column [value="' + data.basename + '"]' );
|
|
|
|
/**
|
|
* Object for the primary list table row for this plugin.
|
|
* @type {Object} jQuery
|
|
*/
|
|
this.$row = this.$check.closest( 'tr' );
|
|
|
|
/**
|
|
* Object for the container which holds update notices for this plugin.
|
|
* This container represents the main difference between the two list tables.
|
|
*
|
|
* This property is only initialized for plugins with license errors.
|
|
*
|
|
* @type {Object} jQuery
|
|
*/
|
|
this.$noticeContainer = null;
|
|
};
|
|
|
|
/**
|
|
* Get the html for this plugin's check license again link.
|
|
*
|
|
* @returns {string}
|
|
*/
|
|
Plugin.prototype.checkAgainLink = function() {
|
|
return ' <span class="as3cf-dbrains-check-my-licence-again"><a href="#">' + as3cf_dbrains.strings.check_licence_again + '</a></span>';
|
|
};
|
|
|
|
/**
|
|
* Does this plugin have any errors for its license?
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
Plugin.prototype.hasLicenseErrors = function() {
|
|
const license = this.isAddon() ? this.parent.data.license : this.data.license;
|
|
|
|
return !_.isEmpty( license.errors );
|
|
};
|
|
|
|
/**
|
|
* Disable the plugin's list table checkbox.
|
|
*/
|
|
Plugin.prototype.disableUpdateCheckbox = function() {
|
|
if ( $listTable.is( '#update-plugins-table' ) ) {
|
|
this.$check.prop( {
|
|
disabled: true,
|
|
checked: false
|
|
} );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Enable the plugin's list table checkbox.
|
|
*/
|
|
Plugin.prototype.enableUpdateCheckbox = function() {
|
|
if ( $listTable.is( '#update-plugins-table' ) ) {
|
|
this.$check.prop( {
|
|
disabled: false
|
|
} );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set the update notice with the given html.
|
|
*
|
|
* @param {string} html
|
|
*/
|
|
Plugin.prototype.setNotice = function( html ) {
|
|
this.$noticeContainer.find( '.as3cf-licence-notice' ).remove();
|
|
this.$noticeContainer.append(
|
|
'<div class="as3cf-licence-notice update-message notice inline notice-warning notice-alt">' +
|
|
'<p class="as3cf-before">' + html + this.checkAgainLink() + '</p>' +
|
|
'</div>'
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Fade out our license notice and remove it, then restore WP update notices, if any.
|
|
*/
|
|
Plugin.prototype.clearNotice = function() {
|
|
const plugin = this;
|
|
const $notice = this.$noticeContainer.find( '.as3cf-licence-notice' );
|
|
|
|
$.when( $notice.fadeOut() ).done( function() {
|
|
$notice.remove();
|
|
plugin.$row.children().css( 'box-shadow', '' );
|
|
plugin.$noticeContainer.find( '.update-message' ).show();
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* Render the plugin's state to the DOM.
|
|
*/
|
|
Plugin.prototype.render = function() {
|
|
if ( this.hasLicenseErrors() ) {
|
|
this.initNoticeContainer();
|
|
this.disableUpdateCheckbox();
|
|
this.$noticeContainer.find( '.update-message:not(".as3cf-licence-notice")' ).hide();
|
|
this.setNotice( this.getLicenseNotice() );
|
|
} else if ( this.$noticeContainer ) {
|
|
this.enableUpdateCheckbox();
|
|
this.clearNotice();
|
|
}
|
|
|
|
if ( !this.isAddon() ) {
|
|
_.invoke( this.addons, 'render' );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize the notice container.
|
|
*/
|
|
Plugin.prototype.initNoticeContainer = function() {
|
|
if ( this.$noticeContainer ) {
|
|
return;
|
|
}
|
|
|
|
// Check if it is the Plugins update table
|
|
if ( !$listTable.is( '#update-plugins-table' ) ) {
|
|
|
|
// Check for an existing plugin-update notice row to use.
|
|
const $noticeRow = $listTable.find( '.plugin-update-tr[data-plugin="' + this.data.basename + '"]' );
|
|
|
|
if ( $noticeRow.length ) {
|
|
this.$noticeContainer = $noticeRow.find( '.plugin-update' );
|
|
} else {
|
|
|
|
const colspan = this.$row.children().length;
|
|
|
|
// If there is no plugin-update row, the plugin did not have an update, so inject a row to use.
|
|
this.$row.after(
|
|
'<tr class="plugin-update-tr ' + this.$row.attr( 'class' ) + '" ' +
|
|
'id="' + this.data.slug + '-update" ' +
|
|
'data-slug="' + this.data.slug + '" ' +
|
|
'data-plugin="' + this.data.basename + '" ' +
|
|
'>' +
|
|
'<td colspan="' + colspan + '" class="plugin-update colspanchange"></td>' +
|
|
'</tr>'
|
|
);
|
|
|
|
// The border between rows comes from a box-shadow on the children of the row above
|
|
this.$row.children().css( 'box-shadow', 'none' );
|
|
|
|
this.$noticeContainer = $listTable.find( '.plugin-update-tr[data-plugin="' + this.data.basename + '"] .plugin-update' );
|
|
}
|
|
} else {
|
|
// Updates
|
|
this.$noticeContainer = this.$row.find( '.plugin-title' );
|
|
}
|
|
|
|
// Finally, bind the click handler for ajax license checking
|
|
this.$noticeContainer.on( 'click', '.as3cf-dbrains-check-my-licence-again a', _.bind( this.checkLicenseAgain, this ) );
|
|
};
|
|
|
|
/**
|
|
* Get the text for the license notice.
|
|
*
|
|
* @returns {string}
|
|
*/
|
|
Plugin.prototype.getLicenseNotice = function() {
|
|
let message = '';
|
|
|
|
if ( this.data.update_available ) {
|
|
message = as3cf_dbrains.strings.update_available + ' ';
|
|
}
|
|
|
|
if ( this.isAddon() ) {
|
|
return message + as3cf_dbrains.strings.requires_parent_licence.replace( '%s', this.parent.data.name );
|
|
}
|
|
|
|
return message + _.values( this.data.license.errors ).join( '' );
|
|
};
|
|
|
|
/**
|
|
* Event listener callback to handle the check the license again for this plugin.
|
|
*
|
|
* @param {Event} event
|
|
*/
|
|
Plugin.prototype.checkLicenseAgain = function( event ) {
|
|
const plugin = this;
|
|
const $link = $( event.target );
|
|
const $spinner = $( '<span class="spinner is-active as3cf-dbrains-licence-check-spinner" style="float:none; margin-top: -3px;"></span>' );
|
|
|
|
event.preventDefault();
|
|
|
|
$link.hide().after( $spinner );
|
|
|
|
this.ajaxCheckLicense()
|
|
.done( function( data ) {
|
|
if ( plugin.isAddon() ) {
|
|
plugin.parent.data.license.errors = data.errors;
|
|
plugin.parent.render();
|
|
} else {
|
|
plugin.data.license.errors = data.errors;
|
|
plugin.render();
|
|
}
|
|
} )
|
|
.fail( function() {
|
|
plugin.setNotice( as3cf_dbrains.strings.licence_check_problem );
|
|
} )
|
|
.always( function() {
|
|
$spinner.remove();
|
|
} )
|
|
;
|
|
};
|
|
|
|
/**
|
|
* Send an ajax request to the server to check the plugin's license.
|
|
*
|
|
* @return {jqXHR} jQuery XHR Promise object
|
|
*/
|
|
Plugin.prototype.ajaxCheckLicense = function() {
|
|
const prefix = this.isAddon() ? this.parent.data.prefix : this.data.prefix;
|
|
|
|
return $.ajax( {
|
|
url: ajaxurl,
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
cache: false,
|
|
data: {
|
|
action: prefix + '_check_licence',
|
|
nonce: as3cf_dbrains.nonces.check_licence
|
|
}
|
|
} );
|
|
};
|
|
|
|
/**
|
|
* Initialize the plugin instance.
|
|
*/
|
|
Plugin.prototype.init = function() {
|
|
this.render();
|
|
|
|
if ( !this.isAddon() ) {
|
|
this.initAddons();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Does this instance represent an add-on?
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
Plugin.prototype.isAddon = function() {
|
|
return !!this.parent;
|
|
};
|
|
|
|
/**
|
|
* Initialize Plugin add-ons.
|
|
*/
|
|
Plugin.prototype.initAddons = function() {
|
|
const parent = this;
|
|
|
|
this.addons = _.map( this.data.addons, function( addonData ) {
|
|
return new Plugin( addonData, parent );
|
|
} );
|
|
|
|
_.invoke( this.addons, 'init' );
|
|
};
|
|
|
|
/**
|
|
* Instantiate and initialize plugin instances.
|
|
*/
|
|
function initialize() {
|
|
_.chain( as3cf_dbrains.plugins )
|
|
.map( function( pluginData ) {
|
|
return new Plugin( pluginData );
|
|
} )
|
|
.invoke( 'init' );
|
|
}
|
|
|
|
if ( $listTable.length ) {
|
|
$( initialize );
|
|
}
|
|
})( jQuery );
|