S3 Uploads. * Version: 1.1.0 * Author: Armando Lüscher * Author URI: https://noplanman.ch * Text Domain: advanced-s3-uploads-config * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * * @package Advanced_S3_Uploads_Config */ /** * Copyright 2020 Armando Lüscher (email: armando@noplanman.ch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ declare( strict_types=1 ); namespace noplanman\Advanced_S3_Uploads_Config; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; add_action( 'admin_menu', __NAMESPACE__ . '\check_dependencies', 9 ); add_action( 'admin_init', __NAMESPACE__ . '\register_settings' ); add_action( 'admin_menu', __NAMESPACE__ . '\settings_page' ); // The filter for S3 Uploads that modifies the AWS client connection. add_filter( 's3_uploads_s3_client_params', __NAMESPACE__ . '\get_aws_client_params' ); /** * Make sure S3 Uploads is installed and activated. */ function check_dependencies() { if ( ! current_user_can( 'activate_plugins' ) ) { return; } if ( ! is_plugin_active( 's3-uploads/s3-uploads.php' ) ) { remove_action( 'admin_init', __NAMESPACE__ . '\register_settings' ); remove_action( 'admin_menu', __NAMESPACE__ . '\settings_page' ); remove_filter( 's3_uploads_s3_client_params', __NAMESPACE__ . '\get_aws_client_params' ); deactivate_plugins( plugin_basename( __FILE__ ) ); add_action( 'admin_notices', __NAMESPACE__ . '\admin_notice_missing_plugin' ); add_action( 'network_admin_notices', __NAMESPACE__ . '\admin_notice_missing_plugin' ); } } /** * Admin notice to alert about missing S3 Uploads plugin. */ function admin_notice_missing_plugin() { ?>
%s
', esc_html__( 'Save correct credentials first to load bucket list.', 'advanced-s3-uploads-config' ) ); return; } $buckets = get_bucket_list(); if ( is_wp_error( $buckets ) ) { printf( '%s
', esc_html__( 'Failed to fetch buckets, check your connection details!', 'advanced-s3-uploads-config' ) ); printf( '%s
', esc_html( $buckets->get_error_message() ) ); return; } if ( empty( $buckets ) ) { printf( '%s
', esc_html__( 'No buckets found, please create one first.', 'advanced-s3-uploads-config' ) ); return; } echo ''; } /** * Render the "Use Path Style" checkbox. */ function use_path_style_render(): void { ?> > %s', esc_html__( 'Check this to use "s3.endpoint/bucket" instead of "bucket.s3.endpoint"', 'advanced-s3-uploads-config' ) ); } /** * Render the "Object ACL" input field. */ function object_acl_render(): void { ?> %s', esc_html__( 'Check documentation of your S3 provider for available permissions', 'advanced-s3-uploads-config' ) ); } /** * Render the "Replace Upload URL" checkbox. */ function replace_upload_url_render(): void { ?> > and tags, to link to "URL Rewrites" in the S3 Uploads readme. printf( '%s
', sprintf( esc_html__( 'Serve media from a custom URL (%1$sread more%2$s). Will only come into effect if "Replace Upload URL" is checked.', 'advanced-s3-uploads-config' ), '', '' ) ); } /** * Render the "HTTP Cache Control" input field. */ function http_cache_control_render(): void { ?> %s', esc_html__( 'A plain number will result in "max-age=%s
', sprintf( esc_html__( 'Can be static or dynamic date and time, check %1$sstrtotime%2$s for allowed values', 'advanced-s3-uploads-config' ), '', '' ) ); } /** * Render the "Auto-Enable" checkbox. */ function autoenable_render(): void { ?> > %s', esc_html__( 'If this is unchecked, S3 Uploads must be enabled explicitly with "wp s3-uploads enable" WP-CLI command', 'advanced-s3-uploads-config' ) ); } /** * Render the "Debug" checkbox. */ function debug_render(): void { ?> > %s', esc_html__( 'Set this if uploads are failing, to display debug output and help find the problem', 'advanced-s3-uploads-config' ) ); } /** * Get the list of buckets with the saved credentials. * * @return array|\WP_Error */ function get_bucket_list() { try { $s3_client = \Aws\S3\S3Client::factory( get_aws_client_params( [] ) ); $buckets = $s3_client->listBuckets()->toArray()['Buckets'] ?? []; return array_column( $buckets, 'Name' ); } catch ( \Throwable $e ) { return new \WP_Error( 'as3uc_list_buckets_error', $e->getMessage() ); } } /** * Get a specific option. * * @param null|string $option ID of option to get. * @param mixed $default Override default value if option not found. * * @return mixed */ function get_option( $option = null, $default = null ) { static $options = null; if ( null === $options ) { $options = \get_option( 'as3uc_settings' ); } // If no specific option is requested, return them all. if ( null === $option ) { return $options; } // Return found option value or default. return $options[ $option ] ?? $default; } /** * Filter S3 Uploads AWS S3 client parameters. * * @param array $params AWS S3 Factory parameters. * * @return array */ function get_aws_client_params( array $params ): array { if ( ( $key = get_option( 'key' ) ) && $secret = get_option( 'secret' ) ) { $params['credentials']['key'] = $key; $params['credentials']['secret'] = $secret; } if ( $endpoint = get_option( 'endpoint' ) ) { $params['endpoint'] = $endpoint; } if ( $region = get_option( 'region' ) ) { $params['region'] = $region; } $params['use_path_style_endpoint'] = (bool) get_option( 'use_path_style' ); $params['version'] = get_option( 'api_version' ) ?: 'latest'; $params['signature'] = get_option( 'api_signature' ) ?: 'v4'; if ( (bool) get_option( 'debug', false ) ) { $params['debug'] = [ 'logfn' => __NAMESPACE__ . '\aws_debug_log_callback' ]; } // Make sure to use WP proxy if one is set. if ( defined( 'WP_PROXY_HOST' ) && defined( 'WP_PROXY_PORT' ) ) { $proxy_auth = ''; $proxy_address = WP_PROXY_HOST . ':' . WP_PROXY_PORT; if ( defined( 'WP_PROXY_USERNAME' ) && defined( 'WP_PROXY_PASSWORD' ) ) { $proxy_auth = WP_PROXY_USERNAME . ':' . WP_PROXY_PASSWORD . '@'; } $params['request.options']['proxy'] = $proxy_auth . $proxy_address; } return $params; } /** * Callback for the AWS client debug output. * * @todo Maybe add an option to output to a file? * * @param string $message The log message itself. */ function aws_debug_log_callback( string $message ): void { // Note: Simply outputting debug info breaks AJAX requests! echo esc_html( $message ); } // Now, let's actually set the constants! $as3uc_settings = [ 'key' => 'S3_UPLOADS_KEY', 'secret' => 'S3_UPLOADS_SECRET', 'endpoint' => 'S3_UPLOADS_ENDPOINT', 'region' => 'S3_UPLOADS_REGION', 'bucket' => 'S3_UPLOADS_BUCKET', 'bucket_url' => 'S3_UPLOADS_BUCKET_URL', 'object_acl' => 'S3_UPLOADS_OBJECT_ACL', 'http_cache_control' => 'S3_UPLOADS_HTTP_CACHE_CONTROL', ]; foreach ( $as3uc_settings as $as3uc_setting => $s3u_const ) { if ( $option = get_option( $as3uc_setting ) ) { defined( $s3u_const ) || define( $s3u_const, $option ); } } if ( ! defined( 'S3_UPLOADS_HTTP_EXPIRES' ) && ( $http_expires = get_option( 'http_expires' ) ) ) { // Convert the setting into an http-date timestamp. $http_expires = strtotime( $http_expires ); if ( is_numeric( $http_expires ) ) { define( 'S3_UPLOADS_HTTP_EXPIRES', gmdate( DATE_RFC7231, $http_expires ) ); } } if ( ! defined( 'S3_UPLOADS_DISABLE_REPLACE_UPLOAD_URL' ) ) { define( 'S3_UPLOADS_DISABLE_REPLACE_UPLOAD_URL', ! (bool) get_option( 'replace_upload_url' ) ); } if ( ! defined( 'S3_UPLOADS_AUTOENABLE' ) ) { define( 'S3_UPLOADS_AUTOENABLE', (bool) get_option( 'autoenable', false ) ); }