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
670 lines
17 KiB
PHP
670 lines
17 KiB
PHP
<?php
|
|
|
|
namespace DeliciousBrains\WP_Offload_Media\Pro\Integrations\Assets;
|
|
|
|
use Amazon_S3_And_CloudFront_Pro;
|
|
use AS3CF_Utils;
|
|
use DeliciousBrains\WP_Offload_Media\API\V1\State;
|
|
use DeliciousBrains\WP_Offload_Media\Integrations\Integration;
|
|
use DeliciousBrains\WP_Offload_Media\Pro\Integrations\Assets\API\V1\Assets_Domain_Check;
|
|
use DeliciousBrains\WP_Offload_Media\Pro\Integrations\Assets\API\V1\Assets_Settings;
|
|
use DeliciousBrains\WP_Offload_Media\Settings\Domain_Check;
|
|
use DeliciousBrains\WP_Offload_Media\Settings\Exceptions\Domain_Check_Exception;
|
|
use DeliciousBrains\WP_Offload_Media\Settings\Validator_Interface;
|
|
use DeliciousBrains\WP_Offload_Media\Settings_Interface;
|
|
use DeliciousBrains\WP_Offload_Media\Settings_Trait;
|
|
use DeliciousBrains\WP_Offload_Media\Settings_Validator_Trait;
|
|
use Exception;
|
|
use WP_Error as AS3CF_Result;
|
|
|
|
class Assets extends Integration implements Settings_Interface, Validator_Interface {
|
|
use Settings_Trait;
|
|
use Settings_Validator_Trait;
|
|
|
|
const SETTINGS_KEY = 'as3cf_assets_pull';
|
|
const VALIDATOR_KEY = 'assets';
|
|
|
|
/**
|
|
* @var Amazon_S3_And_CloudFront_Pro
|
|
*/
|
|
protected $as3cf;
|
|
|
|
/**
|
|
* Cache property of whether integration is enabled.
|
|
*
|
|
* @var bool
|
|
*/
|
|
private $enabled;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
protected static $settings_constants = array(
|
|
'AS3CF_ASSETS_PULL_SETTINGS',
|
|
'WPOS3_ASSETS_PULL_SETTINGS',
|
|
);
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public static function is_installed(): bool {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Is this integration enabled?
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_enabled(): bool {
|
|
if ( is_null( $this->enabled ) ) {
|
|
if ( parent::is_enabled() && $this->as3cf->feature_enabled( 'assets' ) ) {
|
|
$this->enabled = true;
|
|
} else {
|
|
$this->enabled = false;
|
|
}
|
|
}
|
|
|
|
return $this->enabled;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function init() {
|
|
// UI - Common
|
|
add_filter( 'as3cfpro_js_strings', array( $this, 'add_js_strings' ) );
|
|
|
|
// Don't enable the remaining hooks unless integration enabled.
|
|
if ( ! $this->is_enabled() ) {
|
|
return;
|
|
}
|
|
|
|
// UI - Enabled
|
|
add_filter( 'as3cfpro_js_config', array( $this, 'add_js_config' ) );
|
|
add_filter( 'as3cf_get_docs', array( $this, 'get_docs' ) );
|
|
|
|
// REST-API
|
|
add_filter( 'as3cf_api_endpoints', array( $this, 'add_api_endpoints' ) );
|
|
add_filter(
|
|
$this->as3cf->get_plugin_prefix() . '_api_response_get_' . State::name(),
|
|
array( $this, 'api_get_state' )
|
|
);
|
|
|
|
// Support
|
|
add_filter( 'as3cf_diagnostic_info', array( $this, 'diagnostic_info' ) );
|
|
|
|
// Keep track of whether the settings we're responsible for are currently being saved.
|
|
add_action( 'as3cf_pre_save_assets_settings', function () {
|
|
$this->set_saving_settings( true );
|
|
} );
|
|
add_action( 'as3cf_post_save_assets_settings', function () {
|
|
$this->set_saving_settings( false );
|
|
} );
|
|
|
|
// Register this instance as a validator.
|
|
$this->as3cf->validation_manager->register_validator( self::VALIDATOR_KEY, $this );
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function setup() {
|
|
// Don't enable the hooks unless integration and URL rewriting enabled.
|
|
if ( ! $this->is_enabled() || ! $this->should_rewrite_urls() ) {
|
|
return;
|
|
}
|
|
|
|
// URL Rewriting.
|
|
add_filter( 'style_loader_src', array( $this, 'rewrite_src' ), 10, 2 );
|
|
add_filter( 'script_loader_src', array( $this, 'rewrite_src' ), 10, 2 );
|
|
add_filter( 'as3cf_get_asset', array( $this, 'rewrite_src' ) );
|
|
add_filter( 'wp_resource_hints', array( $this, 'register_resource_hints' ), 10, 2 );
|
|
}
|
|
|
|
/*
|
|
* Settings Interface
|
|
*/
|
|
|
|
/**
|
|
* Accessor for a plugin setting with conditions for defaults and upgrades.
|
|
*
|
|
* @param string $key
|
|
* @param mixed $default
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function get_setting( string $key, $default = '' ) {
|
|
$settings = $this->get_settings();
|
|
|
|
$value = isset( $settings[ $key ] ) ? $settings[ $key ] : $default;
|
|
|
|
if ( 'rewrite-urls' == $key && ! isset( $settings[ $key ] ) ) {
|
|
$value = false;
|
|
}
|
|
|
|
if ( 'force-https' == $key && ! isset( $settings[ $key ] ) ) {
|
|
$value = false;
|
|
}
|
|
|
|
return apply_filters( 'as3cf_assets_pull_setting_' . $key, $value );
|
|
}
|
|
|
|
/**
|
|
* Allowed settings keys for this plugin.
|
|
*
|
|
* @param bool $include_legacy Should legacy keys be included? Optional, default false.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_allowed_settings_keys( bool $include_legacy = false ): array {
|
|
return array(
|
|
'rewrite-urls',
|
|
'domain',
|
|
'force-https',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_sensitive_settings(): array {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_monitored_settings_blacklist(): array {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_skip_sanitize_settings(): array {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_path_format_settings(): array {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_prefix_format_settings(): array {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function get_boolean_format_settings(): array {
|
|
return array(
|
|
'rewrite-urls',
|
|
'force-https',
|
|
);
|
|
}
|
|
|
|
/*
|
|
* UI
|
|
*/
|
|
|
|
/**
|
|
* Add additional translated strings for integration.
|
|
*
|
|
* @param array $strings
|
|
*
|
|
* @return array
|
|
*/
|
|
public function add_js_strings( array $strings ): array {
|
|
return array_merge( $strings, array(
|
|
'assets_panel_header' => _x( 'Assets Pull', 'Assets panel title', 'amazon-s3-and-cloudfront' ),
|
|
'assets_panel_header_details' => _x( 'Deliver scripts, styles, fonts and other assets from a content delivery network.', 'Assets panel details', 'amazon-s3-and-cloudfront' ),
|
|
'assets_rewrite_urls' => _x( 'Rewrite Asset URLs', 'Setting title', 'amazon-s3-and-cloudfront' ),
|
|
'assets_rewrite_urls_desc' => _x( 'Change the URLs of any enqueued asset files to use a CDN domain.', 'Setting description', 'amazon-s3-and-cloudfront' ),
|
|
'assets_force_https' => _x( 'Force HTTPS', 'Setting title', 'amazon-s3-and-cloudfront' ),
|
|
'assets_force_https_desc' => _x( 'Uses HTTPS for every rewritten asset URL instead of using the scheme of the current page.', 'Setting description', 'amazon-s3-and-cloudfront' ),
|
|
'assets_domain_same_as_site' => __( "Domain cannot be the same as the site's domain; use a subdomain instead.", 'amazon-s3-and-cloudfront' ),
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Add additional config for integration.
|
|
*
|
|
* @param array $config
|
|
*
|
|
* @return array
|
|
*/
|
|
public function add_js_config( array $config ): array {
|
|
return array_merge(
|
|
$config,
|
|
$this->as3cf->get_api_manager()->get_api_endpoint(
|
|
Assets_Settings::name()
|
|
)->common_response()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add doc links for this integration.
|
|
*
|
|
* @handles as3cf_docs_data
|
|
*
|
|
* @param array $docs_data
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_docs( array $docs_data ): array {
|
|
$docs_data['assets-pull'] = array(
|
|
'url' => $this->as3cf::dbrains_url( '/wp-offload-media/doc/assets-quick-start-guide', array( 'utm_campaign' => 'WP+Offload+S3', 'assets+doc' => 'assets-tab' ) ),
|
|
'desc' => _x( 'Click to view help doc on our site', 'Help icon alt text', 'amazon-s3-and-cloudfront' ),
|
|
);
|
|
|
|
return $docs_data;
|
|
}
|
|
|
|
/*
|
|
* REST-API
|
|
*/
|
|
|
|
/**
|
|
* Add API endpoints.
|
|
*
|
|
* @handles as3cf_api_endpoints
|
|
*
|
|
* @param array $api_endpoints
|
|
*
|
|
* @return array
|
|
*/
|
|
public function add_api_endpoints( array $api_endpoints ): array {
|
|
return array_merge( $api_endpoints, array(
|
|
Assets_Domain_Check::name() => new Assets_Domain_Check( $this->as3cf ),
|
|
Assets_Settings::name() => new Assets_Settings( $this->as3cf ),
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Add additional config into state API responses.
|
|
*
|
|
* @param array $response
|
|
*
|
|
* @return array
|
|
*/
|
|
public function api_get_state( array $response ): array {
|
|
return array_merge(
|
|
$response,
|
|
$this->as3cf->get_api_manager()->get_api_endpoint(
|
|
Assets_Settings::name()
|
|
)->common_response()
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Support
|
|
*/
|
|
|
|
/**
|
|
* Integration specific diagnostic info.
|
|
*
|
|
* @param string $output
|
|
*
|
|
* @return string
|
|
*/
|
|
public function diagnostic_info( string $output = '' ): string {
|
|
$output .= 'Assets Pull:';
|
|
$output .= "\r\n";
|
|
|
|
$output .= 'Rewrite URLs: ';
|
|
$output .= $this->on_off( 'rewrite-urls' );
|
|
$output .= "\r\n";
|
|
|
|
$output .= 'Domain: ';
|
|
$output .= esc_html( $this->get_setting( 'domain' ) );
|
|
$output .= "\r\n";
|
|
|
|
$output .= 'Force HTTPS: ';
|
|
$output .= $this->on_off( 'force-https' );
|
|
$output .= "\r\n";
|
|
|
|
$output .= 'Domain Check: ';
|
|
$output .= $this->diagnostic_domain_check();
|
|
$output .= "\r\n\r\n";
|
|
|
|
$output .= 'AS3CF_ASSETS_PULL_SETTINGS: ';
|
|
|
|
$settings_constant = static::settings_constant();
|
|
|
|
if ( $settings_constant ) {
|
|
$output .= 'Defined';
|
|
|
|
if ( 'AS3CF_ASSETS_PULL_SETTINGS' !== $settings_constant ) {
|
|
$output .= ' (using ' . $settings_constant . ')';
|
|
}
|
|
|
|
$defined_settings = $this->get_defined_settings();
|
|
if ( empty( $defined_settings ) ) {
|
|
$output .= ' - *EMPTY*';
|
|
} else {
|
|
$output .= "\r\n";
|
|
$output .= 'AS3CF_ASSETS_PULL_SETTINGS Keys: ' . implode( ', ', array_keys( $defined_settings ) );
|
|
}
|
|
} else {
|
|
$output .= 'Not defined';
|
|
}
|
|
$output .= "\r\n";
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Run a domain check on the configured domain for the diagnostic information.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function diagnostic_domain_check(): string {
|
|
$domain = $this->get_setting( 'domain' );
|
|
|
|
if ( empty( $domain ) ) {
|
|
return '(no domain)';
|
|
}
|
|
|
|
$check = new Domain_Check( $domain );
|
|
|
|
try {
|
|
$this->run_domain_check( $check );
|
|
} catch ( Exception $e ) {
|
|
return $e->getMessage();
|
|
}
|
|
|
|
return 'OK';
|
|
}
|
|
|
|
/*
|
|
* Domain Check
|
|
*/
|
|
|
|
/**
|
|
* Check given domain is configured correctly.
|
|
*
|
|
* @param string $domain
|
|
*
|
|
* @return array
|
|
*/
|
|
public function check_domain( string $domain ): array {
|
|
$check = new Domain_Check( $domain );
|
|
|
|
try {
|
|
$this->run_domain_check( $check );
|
|
} catch ( Exception $e ) {
|
|
return array(
|
|
'success' => false,
|
|
'domain' => $check->domain(),
|
|
'message' => _x( 'Assets cannot be delivered from the CDN.', 'Assets domain check error', 'amazon-s3-and-cloudfront' ),
|
|
'error' => $e->getMessage(),
|
|
'link' => $this->domain_check_more_info_link( $e ),
|
|
'timestamp' => current_time( 'timestamp' ),
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'success' => true,
|
|
'domain' => $check->domain(),
|
|
'message' => _x( 'Assets are serving from the CDN with the configured domain name.', 'Assets domain check success for active domain', 'amazon-s3-and-cloudfront' ),
|
|
'timestamp' => current_time( 'timestamp' ),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Build a "More info" link for a domain check error message.
|
|
*
|
|
* @param string|Exception $message
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function domain_check_more_info_link( $message ): string {
|
|
$exception = $message;
|
|
|
|
if ( $message instanceof Exception ) {
|
|
$message = $exception->getMessage();
|
|
}
|
|
|
|
$utm_content = 'assets+domain+check';
|
|
|
|
if ( $exception instanceof Domain_Check_Exception ) {
|
|
return $this->as3cf->more_info_link( $exception->more_info(), $utm_content, $exception->get_key() );
|
|
}
|
|
|
|
// Fall-back to a search of the docs.
|
|
return $this->as3cf->more_info_link( '/wp-offload-media/docs/?swpquery=' . urlencode( $message ), $utm_content );
|
|
}
|
|
|
|
/**
|
|
* Execute the given domain check.
|
|
*
|
|
* @param Domain_Check $check
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
protected function run_domain_check( Domain_Check $check ) {
|
|
$test_time = microtime();
|
|
$test_key = base64_encode( $test_time ); //phpcs:ignore
|
|
|
|
$this->test_assets_endpoint( $check, $test_key, $test_time );
|
|
}
|
|
|
|
/**
|
|
* Send a request to the test endpoint and make assertions about the response.
|
|
*
|
|
* @param Domain_Check $check
|
|
* @param string $key
|
|
* @param string $ver
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
protected function test_assets_endpoint( Domain_Check $check, string $key, string $ver ) {
|
|
/** @var Assets_Domain_Check $domain_check */
|
|
$domain_check = $this->as3cf->get_api_manager()->get_api_endpoint(
|
|
Assets_Domain_Check::name()
|
|
);
|
|
|
|
$test_endpoint = $domain_check->get_url( $key );
|
|
$test_endpoint = add_query_arg( compact( 'ver' ), $test_endpoint );
|
|
$test_endpoint = $this->rewrite_url( $test_endpoint );
|
|
|
|
$response = $check->test_rest_endpoint( $test_endpoint );
|
|
|
|
$expected = new Domain_Check_Response( compact( 'key', 'ver' ) );
|
|
$expected->verify_signature( wp_remote_retrieve_header( $response, 'x-as3cf-signature' ) );
|
|
}
|
|
|
|
/*
|
|
* URL Rewriting
|
|
*/
|
|
|
|
/**
|
|
* Should asset URL rewriting be performed?
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function should_rewrite_urls(): bool {
|
|
// TODO: cache result and reuse.
|
|
|
|
if ( ! $this->get_setting( 'rewrite-urls' ) ) {
|
|
return false;
|
|
}
|
|
|
|
if (
|
|
! Domain_Check::is_valid( $this->get_setting( 'domain' ) ) ||
|
|
$this->as3cf->validation_manager->section_has_error( self::VALIDATOR_KEY )
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if ( is_admin() && ! AS3CF_Utils::is_ajax() && ! AS3CF_Utils::is_rest_api() ) {
|
|
/**
|
|
* If you're really brave, you can have Assets Pull also rewrite enqueued assets
|
|
* within the WordPress admin dashboard.
|
|
*
|
|
* @param bool $rewrite
|
|
*/
|
|
return apply_filters( 'as3cf_assets_enable_wp_admin_rewrite', false );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Should the given asset URL be rewritten?
|
|
*
|
|
* @param mixed $src The asset URL to be rewritten.
|
|
* @param string|null $handle The asset's registered handle in the WordPress enqueue system.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function should_rewrite_src( $src, string $handle = null ): bool {
|
|
// If there is no string to rewrite, the answer is definitely no.
|
|
if ( empty( $src ) || ! is_string( $src ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( AS3CF_Utils::is_relative_url( $src ) ) {
|
|
$rewrite = true;
|
|
} elseif ( AS3CF_Utils::url_domains_match( $src, home_url() ) ) {
|
|
$rewrite = true;
|
|
} else {
|
|
$rewrite = false;
|
|
}
|
|
|
|
/**
|
|
* @param bool $rewrite Should the src be rewritten?
|
|
* @param string $src The asset URL to be rewritten.
|
|
* @param string|null $handle The asset's registered handle in the WordPress enqueue system.
|
|
*/
|
|
return apply_filters( 'as3cf_assets_should_rewrite_src', $rewrite, $src, $handle );
|
|
}
|
|
|
|
/**
|
|
* Rewrite an asset's src.
|
|
*
|
|
* @param mixed $src
|
|
* @param string|null $handle
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function rewrite_src( $src, string $handle = null ) {
|
|
if ( empty( $src ) || ! is_string( $src ) ) {
|
|
return $src;
|
|
}
|
|
|
|
if ( ! $this->should_rewrite_urls() ) {
|
|
return $src;
|
|
}
|
|
|
|
if ( ! static::should_rewrite_src( $src, $handle ) ) {
|
|
return $src;
|
|
}
|
|
|
|
return $this->rewrite_url( $src, $handle );
|
|
}
|
|
|
|
/**
|
|
* Rewrite a URL to use the asset's domain and scheme.
|
|
*
|
|
* @param string $url
|
|
* @param string|null $handle
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function rewrite_url( string $url, string $handle = null ): string {
|
|
$rewritten = 'http://' . $this->get_setting( 'domain' );
|
|
$rewritten .= AS3CF_Utils::parse_url( $url, PHP_URL_PATH );
|
|
$query = AS3CF_Utils::parse_url( $url, PHP_URL_QUERY );
|
|
$rewritten .= $query ? ( '?' . $query ) : '';
|
|
$scheme = $this->get_setting( 'force-https' ) ? 'https' : null;
|
|
|
|
/**
|
|
* Adjust the URL scheme that Assets Pull is going to use for rewritten URL.
|
|
*
|
|
* @param string|null $scheme
|
|
* @param string $url
|
|
* @param string $handle
|
|
*/
|
|
$scheme = apply_filters( 'as3cf_assets_pull_scheme', $scheme, $url, $handle );
|
|
|
|
return set_url_scheme( $rewritten, $scheme );
|
|
}
|
|
|
|
/**
|
|
* Register a DNS prefetch tag for the pull domain if rewriting is enabled.
|
|
*
|
|
* @param array $hints
|
|
* @param string $relation_type
|
|
*
|
|
* @return array
|
|
*/
|
|
public function register_resource_hints( array $hints, string $relation_type ): array {
|
|
if ( 'dns-prefetch' === $relation_type && $this->should_rewrite_urls() ) {
|
|
$hints[] = '//' . $this->get_setting( 'domain' );
|
|
}
|
|
|
|
return $hints;
|
|
}
|
|
|
|
/**
|
|
* Validate settings for Assets.
|
|
*
|
|
* @param bool $force Force time resource consuming or state altering tests to run.
|
|
*
|
|
* @return AS3CF_Result
|
|
*/
|
|
public function validate_settings( bool $force = false ): AS3CF_Result {
|
|
if ( $this->get_setting( 'rewrite-urls' ) ) {
|
|
$domain_check_result = $this->check_domain( $this->get_setting( 'domain' ) );
|
|
|
|
// Did the domain check fail?
|
|
if ( ! $domain_check_result['success'] ) {
|
|
return new AS3CF_Result(
|
|
Validator_Interface::AS3CF_STATUS_MESSAGE_ERROR,
|
|
sprintf(
|
|
_x( '%1$s %2$s In the meantime local assets are being served. %3$s', 'Assets notice for domain issue', 'amazon-s3-and-cloudfront' ),
|
|
$domain_check_result['message'],
|
|
$domain_check_result['error'],
|
|
$domain_check_result['link']
|
|
)
|
|
);
|
|
}
|
|
|
|
// All good.
|
|
return new AS3CF_Result(
|
|
Validator_Interface::AS3CF_STATUS_MESSAGE_SUCCESS,
|
|
$domain_check_result['message']
|
|
);
|
|
} else {
|
|
return new AS3CF_Result(
|
|
Validator_Interface::AS3CF_STATUS_MESSAGE_WARNING,
|
|
sprintf(
|
|
__(
|
|
'Assets cannot be delivered from the CDN until <strong>Rewrite Asset URLs</strong> is enabled. In the meantime, local assets are being served. <a href="%1$s" target="_blank">View Assets Quick Start Guide</a>',
|
|
'amazon-s3-and-cloudfront'
|
|
),
|
|
$this->as3cf::dbrains_url( '/wp-offload-media/doc/assets-quick-start-guide', array( 'utm_campaign' => 'WP+Offload+S3', 'assets+doc' => 'assets-tab' ) )
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the name of the actions that are fired when the settings that the validator
|
|
* is responsible for are saved.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function post_save_settings_actions(): array {
|
|
return array( 'as3cf_post_save_assets_settings' );
|
|
}
|
|
}
|