feat: add S3-compatible storage provider (MinIO, Ceph, R2, etc.)
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
This commit is contained in:
290
classes/pro/tools-manager.php
Normal file
290
classes/pro/tools-manager.php
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
namespace DeliciousBrains\WP_Offload_Media\Pro;
|
||||
|
||||
use Amazon_S3_And_CloudFront_Pro;
|
||||
use DeliciousBrains\WP_Offload_Media\API\V1\State;
|
||||
|
||||
class Tools_Manager {
|
||||
|
||||
/**
|
||||
* @var Tools_Manager
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Registered tools.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tools = array();
|
||||
|
||||
/**
|
||||
* Make this class a singleton.
|
||||
*
|
||||
* Use this instead of __construct().
|
||||
*
|
||||
* @param Amazon_S3_And_CloudFront_Pro $as3cf
|
||||
*
|
||||
* @return Tools_Manager
|
||||
*/
|
||||
public static function get_instance( $as3cf ) {
|
||||
if ( ! isset( static::$instance ) && ! ( self::$instance instanceof Tools_Manager ) ) {
|
||||
static::$instance = new Tools_Manager();
|
||||
// Initialize the class
|
||||
static::$instance->init( $as3cf );
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*
|
||||
* @param Amazon_S3_And_CloudFront_Pro $as3cf
|
||||
*/
|
||||
private function init( $as3cf ) {
|
||||
add_filter( 'as3cfpro_js_strings', array( $this, 'add_strings' ) );
|
||||
add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) ); // phpcs:ignore WordPress.WP.CronInterval
|
||||
add_filter( $as3cf->get_plugin_prefix() . '_api_response_get_' . State::name(), array( $this, 'api_response' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional translated strings for tools.
|
||||
*
|
||||
* @param array $strings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_strings( $strings ) {
|
||||
return array_merge( $strings, array(
|
||||
'pause_button' => _x( 'Pause', 'Button text', 'amazon-s3-and-cloudfront' ),
|
||||
'resume_button' => _x( 'Resume', 'Button text', 'amazon-s3-and-cloudfront' ),
|
||||
'disabled_tool_button' => _x( 'Disabled because another background process is running.', 'Disabled button tooltip', 'amazon-s3-and-cloudfront' ),
|
||||
'disabled_tool_bucket_access' => _x( 'Disabled because this tool requires write access to the bucket.', 'Disabled button tooltip', 'amazon-s3-and-cloudfront' ),
|
||||
'item' => __( 'Item', 'amazon-s3-and-cloudfront' ),
|
||||
'media_library_item' => _x( 'Media Library Item', 'Source type for item error', 'amazon-s3-and-cloudfront' ),
|
||||
'edit_item' => _x( 'Edit', 'Link title', 'amazon-s3-and-cloudfront' ),
|
||||
'dismiss_all' => _x( 'Dismiss All', 'Link title', 'amazon-s3-and-cloudfront' ),
|
||||
'dismiss' => _x( 'Dismiss', 'Link title', 'amazon-s3-and-cloudfront' ),
|
||||
|
||||
// No tools to show yet
|
||||
'no_tools_header' => _x( 'No Tools Available (Yet)', 'No tools graphic', 'amazon-s3-and-cloudfront' ),
|
||||
'no_tools_description' => _x( 'Once an active license and media items are detected, the following tools will become available for bulk management between this server and the storage provider.', 'No tools graphic', 'amazon-s3-and-cloudfront' ),
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cron schedules.
|
||||
*
|
||||
* @param array $schedules
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function cron_schedules( $schedules ) {
|
||||
if ( property_exists( $this, 'cron_interval' ) ) {
|
||||
$interval = apply_filters( 'as3cf_tool_cron_interval', $this->cron_interval );
|
||||
} else {
|
||||
$interval = apply_filters( 'as3cf_tool_cron_interval', 1 );
|
||||
}
|
||||
|
||||
if ( 1 === $interval ) {
|
||||
$display = __( 'Every Minute', 'amazon-s3-and-cloudfront' );
|
||||
} else {
|
||||
$display = sprintf( __( 'Every %d Minutes', 'amazon-s3-and-cloudfront' ), $interval );
|
||||
}
|
||||
|
||||
// Adds our schedule to the existing schedules.
|
||||
$schedules['as3cf_tool_cron_interval'] = array(
|
||||
'interval' => MINUTE_IN_SECONDS * $interval,
|
||||
'display' => $display,
|
||||
);
|
||||
|
||||
return $schedules;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a get state API response is an array without any info for tools, add tools info.
|
||||
*
|
||||
* @handles as3cf_api_response_get_state
|
||||
*
|
||||
* @param mixed $response
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function api_response( $response ) {
|
||||
if ( empty( $response ) || is_wp_error( $response ) || ! is_array( $response ) || isset( $response['tools'] ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['tools'] = $this->get_tools_info();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a tool.
|
||||
*
|
||||
* @param Tool $tool
|
||||
* @param string $context
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function register_tool( Tool $tool, $context = 'background' ) {
|
||||
if ( ! empty( $this->tools[ $context ][ $tool->get_tool_key() ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->tools[ $context ][ $tool->get_tool_key() ] = $tool;
|
||||
|
||||
$tool->priority( $this->get_tools_count() )->init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tool.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool|Tool
|
||||
*/
|
||||
public function get_tool( $name ) {
|
||||
foreach ( $this->tools as $context ) {
|
||||
if ( array_key_exists( $name, $context ) ) {
|
||||
return $context[ $name ];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tools count.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_tools_count() {
|
||||
$count = 0;
|
||||
|
||||
foreach ( $this->tools as $context ) {
|
||||
$count += count( $context );
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all tools.
|
||||
*
|
||||
* @param string $context Optional context to restrict by.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tools( $context = null ) {
|
||||
$result = array();
|
||||
|
||||
foreach ( $this->tools as $_context => $tools ) {
|
||||
if ( ! empty( $context ) && $_context !== $context ) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* @var string $key
|
||||
* @var Tool $tool
|
||||
*/
|
||||
foreach ( $tools as $key => $tool ) {
|
||||
$result[ $key ] = $tool;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tool's info, including current status.
|
||||
*
|
||||
* @param string $context Optional context to restrict by.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tools_info( $context = null ) {
|
||||
$data = array();
|
||||
|
||||
/** @var Tool $tool */
|
||||
foreach ( $this->get_tools( $context ) as $key => $tool ) {
|
||||
$data[ $key ] = $tool->get_info();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get running tool, or null if none running.
|
||||
*
|
||||
* @param string $context Optional context to restrict by.
|
||||
*
|
||||
* @return Tool|null
|
||||
*/
|
||||
public function get_running_tool( $context = null ) {
|
||||
/** @var Tool $tool */
|
||||
foreach ( $this->get_tools( $context ) as $tool ) {
|
||||
$data = $tool->get_info();
|
||||
|
||||
if ( ! empty( $data['is_processing'] ) || ! empty( $data['is_queued'] ) || ! empty( $data['is_paused'] ) ) {
|
||||
return $tool;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try and perform the requested action for a tool identified by its key.
|
||||
*
|
||||
* @param string $tool_key
|
||||
* @param string $action
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function perform_action( $tool_key, $action ) {
|
||||
$tool = $this->get_tool( $tool_key );
|
||||
|
||||
if ( false === $tool ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! method_exists( $tool, 'handle_' . $action ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$running_tool = $this->get_running_tool();
|
||||
|
||||
// Only one tool can be running or interacted with at once.
|
||||
if ( ! empty( $running_tool ) && $tool->get_tool_key() !== $running_tool->get_tool_key() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
call_user_func( array( $tool, 'handle_' . $action ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected constructor to prevent creating a new instance of the
|
||||
* class via the `new` operator from outside this class.
|
||||
*/
|
||||
protected function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* As this class is a singleton it should not be clone-able.
|
||||
*/
|
||||
protected function __clone() {
|
||||
}
|
||||
|
||||
/**
|
||||
* As this class is a singleton it should not be able to be un-serialized.
|
||||
*/
|
||||
public function __wakeup() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user