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
117 lines
2.7 KiB
JavaScript
117 lines
2.7 KiB
JavaScript
import {derived, writable, get} from "svelte/store";
|
|
import {wrap} from "svelte-spa-router/wrap";
|
|
|
|
/**
|
|
* Creates store of default pages.
|
|
*
|
|
* Having a title means inclusion in main tabs.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
function createPages() {
|
|
// NOTE: get() only resolves after initialization, hence arrow functions for getting titles.
|
|
const { subscribe, set, update } = writable( [] );
|
|
|
|
return {
|
|
subscribe,
|
|
set,
|
|
add( page ) {
|
|
update( $pages => {
|
|
return [...$pages, page]
|
|
.sort( ( a, b ) => {
|
|
return a.position - b.position;
|
|
} );
|
|
} );
|
|
},
|
|
withPrefix( prefix = null ) {
|
|
return get( this ).filter( ( page ) => {
|
|
return (prefix && page.route.startsWith( prefix )) || !prefix;
|
|
} );
|
|
},
|
|
routes( prefix = null ) {
|
|
let defaultComponent = null;
|
|
let defaultUserData = null;
|
|
const routes = new Map();
|
|
|
|
// If a page can be enabled/disabled, check whether it is enabled before displaying.
|
|
const conditions = [
|
|
( detail ) => {
|
|
if (
|
|
detail.hasOwnProperty( "userData" ) &&
|
|
detail.userData.hasOwnProperty( "page" ) &&
|
|
detail.userData.page.hasOwnProperty( "enabled" )
|
|
) {
|
|
return detail.userData.page.enabled();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
];
|
|
|
|
for ( const page of this.withPrefix( prefix ) ) {
|
|
const userData = { page: page };
|
|
|
|
let route = page.route;
|
|
|
|
if ( prefix && route !== prefix + "/*" ) {
|
|
route = route.replace( prefix, "" );
|
|
}
|
|
|
|
routes.set( route, wrap( {
|
|
component: page.component,
|
|
userData: userData,
|
|
conditions: conditions
|
|
} ) );
|
|
|
|
if ( !defaultComponent && page.default ) {
|
|
defaultComponent = page.component;
|
|
defaultUserData = userData;
|
|
}
|
|
}
|
|
|
|
if ( defaultComponent ) {
|
|
routes.set( "*", wrap( {
|
|
component: defaultComponent,
|
|
userData: defaultUserData,
|
|
conditions: conditions
|
|
} ) );
|
|
}
|
|
|
|
return routes;
|
|
},
|
|
handleRouteEvent( detail ) {
|
|
if ( detail.hasOwnProperty( "event" ) ) {
|
|
if ( !detail.hasOwnProperty( "data" ) ) {
|
|
detail.data = {};
|
|
}
|
|
|
|
// Find the first page that wants to handle the event
|
|
// , but also let other pages see the event
|
|
// so they can set any initial state etc.
|
|
let route = false;
|
|
for ( const page of get( this ).values() ) {
|
|
if ( page.events && page.events[ detail.event ] && page.events[ detail.event ]( detail.data ) && !route ) {
|
|
route = page.route;
|
|
}
|
|
}
|
|
|
|
if ( route ) {
|
|
return route;
|
|
}
|
|
}
|
|
|
|
if ( detail.hasOwnProperty( "default" ) ) {
|
|
return detail.default;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
};
|
|
}
|
|
|
|
export const pages = createPages();
|
|
|
|
// Convenience readable store of all routes.
|
|
export const routes = derived( pages, () => {
|
|
return pages.routes();
|
|
} ); |