rebase from live enviornment

This commit is contained in:
Rachit Bhargava
2024-01-09 22:14:20 -05:00
parent ff0b49a046
commit 3a22fcaa4a
15968 changed files with 2344674 additions and 45234 deletions

View File

@@ -47,7 +47,7 @@ class AdminBarMenu {
if (
is_user_logged_in() &&
current_user_can( 'manage_options' )
current_user_can( wp_mail_smtp()->get_capability_manage_options() )
) {
$access = true;
}

View File

@@ -138,7 +138,7 @@ class Area {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
return;
}
@@ -177,6 +177,13 @@ class Area {
WP::ADMIN_NOTICE_ERROR
);
break;
case 'google_unsuccessful_oauth':
WP::add_admin_notice(
esc_html__( 'There was an error while processing the authentication request.', 'wp-mail-smtp' ),
WP::ADMIN_NOTICE_ERROR
);
break;
}
switch ( $success ) {
@@ -244,6 +251,17 @@ class Area {
return;
}
/*
* Don't display the notice if the user installed a plugin with a new "Email Test"
* location (starting from v3.9.0) and is not aware of the old one. Also, don't display
* the notice if the `wp_mail_smtp_initial_version` option is not set (it can happen if
* the plugin was activated network wise in the multisite installation and plugin
* activation hook was not performed on the subsite level).
*/
if ( version_compare( get_option( 'wp_mail_smtp_initial_version', '3.9.0' ), '3.9.0', '>=' ) ) {
return;
}
WP::add_admin_notice(
sprintf(
wp_kses(
@@ -285,7 +303,7 @@ class Area {
public function add_admin_options_page() {
// Options pages access capability.
$access_capability = 'manage_options';
$access_capability = wp_mail_smtp()->get_capability_manage_options();
$this->hook = add_menu_page(
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
@@ -348,7 +366,7 @@ class Area {
add_menu_page(
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
'manage_options',
wp_mail_smtp()->get_capability_manage_options(),
self::SLUG,
[ $this, 'display_network_product_education_page' ],
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9IiM5ZWEzYTgiIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgdmlld0JveD0iMCAwIDQzIDM0Ij48cGF0aCBkPSJNMC4wMDcsMy41ODVWMjAuNDIxcTAsMy41ODYsMy43NTEsMy41ODVMMjAsMjRWMTlIMzBWMTQuMDE0bDAuOTkxLTFMMzQsMTNWMy41ODVRMzQsMCwzMC4yNDksMEgzLjc1OFEwLjAwNywwLC4wMDcsMy41ODVoMFpNMy41MjQsNi4xNTdhMS40OSwxLjQ5LDAsMCwxLS41MDgtMC45MzUsMS41ODEsMS41ODEsMCwwLDEsLjI3NC0xLjIwOCwxLjQ0OSwxLjQ0OSwwLDAsMSwxLjA5NC0uNjYzLDEuNzU2LDEuNzU2LDAsMCwxLDEuMjUuMzEybDExLjQwOSw3LjcxNkwyOC4zNzQsMy42NjNhMS45NiwxLjk2LDAsMCwxLDEuMjg5LS4zMTIsMS41NDYsMS41NDYsMCwwLDEsMS4wOTQuNjYzLDEuNCwxLjQsMCwwLDEsLjI3MywxLjIwOCwxLjY3LDEuNjcsMCwwLDEtLjU0Ny45MzVMMTcuMDQzLDE3LjIyNVoiLz48cGF0aCBkPSJNMjIsMjhIMzJsLTAuMDA5LDQuNjI0YTEuMTI2LDEuMTI2LDAsMCwwLDEuOTIyLjhsOC4yNS04LjIzNmExLjEyNiwxLjEyNiwwLDAsMCwwLTEuNTk0bC04LjI1LTguMjQxYTEuMTI2LDEuMTI2LDAsMCwwLTEuOTIyLjh2NC44NjZMMjIsMjF2N1oiLz48L3N2Zz4=',
@@ -537,6 +555,10 @@ class Area {
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-upgrade-wp-mail-smtp-to-pro-version/', [ 'medium' => 'plugin-settings', 'content' => 'Pro Mailer Popup - Already purchased' ] ) ),
esc_html__( 'Already purchased?', 'wp-mail-smtp' )
),
'gmail' => [
'one_click_setup_upgrade_title' => wp_kses( __( 'One-Click Setup for Google Mailer <br> is a Pro Feature', 'wp-mail-smtp' ), [ 'br' => [] ] ),
'one_click_setup_upgrade_content' => esc_html__( 'We\'re sorry, One-Click Setup for Google Mailer is not available on your plan. Please upgrade to the Pro plan to unlock all these awesome features.', 'wp-mail-smtp' ),
],
],
'all_mailers_supports' => wp_mail_smtp()->get_providers()->get_supports_all(),
'nonce' => wp_create_nonce( 'wp-mail-smtp-admin' ),
@@ -818,7 +840,10 @@ class Area {
*
* @param string $capability Email logs access capability.
*/
return apply_filters( 'wp_mail_smtp_admin_area_get_logs_access_capability', 'manage_options' );
return apply_filters(
'wp_mail_smtp_admin_area_get_logs_access_capability',
wp_mail_smtp()->get_capability_manage_options()
);
}
/**
@@ -1126,7 +1151,7 @@ class Area {
$data = [];
// Only admins can fire these ajax requests.
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( $data );
}

View File

@@ -6,7 +6,6 @@ use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Debug;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Options;
use WPMailSMTP\Providers\Gmail\Auth;
/**
* Class ConnectionSettings.
@@ -71,39 +70,14 @@ class ConnectionSettings {
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $mailer !== 'gmail' ) : ?>
<input name="wp-mail-smtp[mail][from_email]" type="email"
value="<?php echo esc_attr( $connection_options->get( 'mail', 'from_email' ) ); ?>"
id="wp-mail-smtp-setting-from_email" spellcheck="false"
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>"
<?php disabled( $connection_options->is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ); ?>
/>
<?php else : ?>
<?php
// Gmail mailer From Email selector.
$gmail_auth = new Auth( $this->connection );
$gmail_aliases = $gmail_auth->is_clients_saved() ? $gmail_auth->get_user_possible_send_from_addresses() : [];
?>
<input name="wp-mail-smtp[mail][from_email]" type="email"
value="<?php echo esc_attr( $connection_options->get( 'mail', 'from_email' ) ); ?>"
id="wp-mail-smtp-setting-from_email" spellcheck="false"
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>"
<?php disabled( $connection_options->is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ); ?>
/>
<?php if ( empty( $gmail_aliases ) ) : ?>
<select name="wp-mail-smtp[mail][from_email]" id="wp-mail-smtp-setting-from_email" disabled>
<option value="">
<?php esc_html_e( 'Please first authorize the Gmail mailer below', 'wp-mail-smtp' ); ?>
</option>
</select>
<?php else : ?>
<select name="wp-mail-smtp[mail][from_email]" id="wp-mail-smtp-setting-from_email">
<?php foreach ( $gmail_aliases as $gmail_email_address ) : ?>
<option value="<?php echo esc_attr( $gmail_email_address ); ?>" <?php selected( $connection_options->get( 'mail', 'from_email' ), $gmail_email_address ); ?>>
<?php echo esc_html( $gmail_email_address ); ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<?php endif; ?>
<?php if ( ! in_array( $mailer, [ 'gmail', 'zoho' ], true ) ) : ?>
<?php if ( ! in_array( $mailer, [ 'zoho' ], true ) ) : ?>
<p class="desc">
<?php esc_html_e( 'The email address that emails are sent from.', 'wp-mail-smtp' ); ?>
</p>
@@ -335,8 +309,6 @@ class ConnectionSettings {
*/
public function process( $data, $old_data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.CyclomaticComplexity.TooHigh
$connection_options = $this->connection->get_options();
// When checkbox is unchecked - it's not submitted at all, so we need to define its default false value.
if ( ! isset( $data['mail']['from_email_force'] ) ) {
$data['mail']['from_email_force'] = false;
@@ -372,21 +344,6 @@ class ConnectionSettings {
}
}
// Old and new Gmail client id/secret values are different - we need to invalidate tokens and scroll to Auth button.
if (
$this->connection->get_mailer_slug() === 'gmail' &&
! empty( $data['gmail']['client_id'] ) &&
! empty( $data['gmail']['client_secret'] ) &&
(
$connection_options->get( 'gmail', 'client_id' ) !== $data['gmail']['client_id'] ||
$connection_options->get( 'gmail', 'client_secret' ) !== $data['gmail']['client_secret']
)
) {
unset( $old_data['gmail'] );
$this->scroll_to = '#wp-mail-smtp-setting-row-gmail-authorize';
}
// Prevent redirect to setup wizard from settings page after successful auth.
if (
! empty( $data['mail']['mailer'] ) &&
@@ -395,7 +352,15 @@ class ConnectionSettings {
$data[ $data['mail']['mailer'] ]['is_setup_wizard_auth'] = false;
}
return $data;
/**
* Filters connection data.
*
* @since 3.11.0
*
* @param array $data Connection data.
* @param array $old_data Old connection data.
*/
return apply_filters( 'wp_mail_smtp_admin_connection_settings_process_data', $data, $old_data );
}
/**
@@ -416,24 +381,19 @@ class ConnectionSettings {
) {
// Save correct from email address if Gmail mailer is already configured.
if (
is_array( $data ) && in_array( $data['mail']['mailer'], [ 'gmail' ], true ) &&
! empty( $data['gmail']['client_id'] ) &&
! empty( $data['gmail']['client_secret'] )
) {
$gmail_auth = new Auth( $this->connection );
$gmail_aliases = $gmail_auth->is_clients_saved() ? $gmail_auth->get_user_possible_send_from_addresses() : [];
if ( $data['mail']['mailer'] === 'gmail' ) {
$gmail_auth = wp_mail_smtp()->get_providers()->get_auth( 'gmail', $this->connection );
$user_info = ! $gmail_auth->is_auth_required() ? $gmail_auth->get_user_info() : false;
if (
! empty( $gmail_aliases ) &&
isset( $gmail_aliases[0] ) &&
is_email( $gmail_aliases[0] ) !== false &&
! empty( $user_info['email'] ) &&
is_email( $user_info['email'] ) !== false &&
(
empty( $data['mail']['from_email'] ) ||
! in_array( $data['mail']['from_email'], $gmail_aliases, true )
$data['mail']['from_email'] !== $user_info['email']
)
) {
$data['mail']['from_email'] = $gmail_aliases[0];
$data['mail']['from_email'] = $user_info['email'];
$this->connection->get_options()->set( $data, false, false );
}

View File

@@ -58,7 +58,7 @@ class DashboardWidget {
public function init() {
// This widget should be displayed for certain high-level users only.
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
return;
}
@@ -181,7 +181,7 @@ class DashboardWidget {
check_admin_referer( 'wp_mail_smtp_' . static::SLUG . '_nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
@@ -202,7 +202,7 @@ class DashboardWidget {
check_admin_referer( 'wp_mail_smtp_' . static::SLUG . '_nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}

View File

@@ -100,7 +100,7 @@ class DebugEvents {
wp_send_json_error( esc_html__( 'Access rejected.', 'wp-mail-smtp' ) );
}
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have the capability to perform this action.', 'wp-mail-smtp' ) );
}
@@ -139,7 +139,7 @@ class DebugEvents {
wp_send_json_error( esc_html__( 'Access rejected.', 'wp-mail-smtp' ) );
}
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have the capability to perform this action.', 'wp-mail-smtp' ) );
}

View File

@@ -558,7 +558,7 @@ class Table extends \WP_List_Table {
</div>
<?php
if ( current_user_can( 'manage_options' ) ) {
if ( current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_nonce_field( 'wp_mail_smtp_debug_events', 'wp-mail-smtp-debug-events-nonce', false );
printf(
'<button id="wp-mail-smtp-delete-all-debug-events-button" type="button" class="button">%s</button>',

View File

@@ -92,7 +92,7 @@ class Education {
check_ajax_referer( 'wp-mail-smtp-admin', 'nonce' );
// Check for permissions.
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}

View File

@@ -76,7 +76,7 @@ class Notifications {
$access = false;
if (
current_user_can( 'manage_options' ) &&
current_user_can( wp_mail_smtp()->get_capability_manage_options() ) &&
! Options::init()->get( 'general', 'am_notifications_hidden' )
) {
$access = true;
@@ -512,7 +512,7 @@ class Notifications {
check_ajax_referer( 'wp-mail-smtp-admin', 'nonce' );
// Check for access and required param.
if ( ! current_user_can( 'manage_options' ) || empty( $_POST['id'] ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) || empty( $_POST['id'] ) ) {
wp_send_json_error();
}

View File

@@ -2,9 +2,10 @@
namespace WPMailSMTP\Admin\Pages;
use Plugin_Upgrader;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\PluginsInstallSkin;
use WPMailSMTP\Admin\PluginsInstallUpgrader;
use WPMailSMTP\Helpers\Helpers;
/**
* About tab.
@@ -603,7 +604,14 @@ class AboutTab extends PageAbstract {
)
);
/*
* The `request_filesystem_credentials` function will output a credentials form in case of failure.
* We don't want that, since it will break AJAX response. So just hide output with a buffer.
*/
ob_start();
// phpcs:ignore WPForms.Formatting.EmptyLineAfterAssigmentVariables.AddEmptyLine
$creds = request_filesystem_credentials( $url, '', false, false, null );
ob_end_clean();
// Check for file system permissions.
if ( false === $creds ) {
@@ -617,8 +625,11 @@ class AboutTab extends PageAbstract {
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 );
// Import the plugin upgrader.
Helpers::include_plugin_upgrader();
// Create the plugin upgrader with our custom skin.
$installer = new PluginsInstallUpgrader( new PluginsInstallSkin() );
$installer = new Plugin_Upgrader( new PluginsInstallSkin() );
// Error check.
if ( ! method_exists( $installer, 'install' ) ) {

View File

@@ -6,7 +6,6 @@ use WPMailSMTP\Admin\ConnectionSettings;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\SetupWizard;
use WPMailSMTP\Options;
use WPMailSMTP\Providers\Gmail\Auth;
use WPMailSMTP\WP;
/**

View File

@@ -2,13 +2,16 @@
namespace WPMailSMTP\Admin;
use Automatic_Upgrader_Skin;
/**
* WordPress class extended for on-the-fly plugin installations.
*
* @since 1.5.0
* @since 1.7.1 Removed feedback() method override to be compatible with PHP5.3+ and WP5.3.
* @since 3.11.0 Updated to extend Automatic_Upgrader_Skin.
*/
class PluginsInstallSkin extends \WP_Upgrader_Skin {
class PluginsInstallSkin extends Automatic_Upgrader_Skin {
/**
* Empty out the header of its HTML content and only check to see if it has

View File

@@ -1,581 +0,0 @@
<?php
namespace WPMailSMTP\Admin;
use WP_Error;
use WP_Upgrader;
use WP_Filesystem_Base;
/** \WP_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
/** \Plugin_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
/**
* In WP 5.3 a PHP 5.6 splat operator (...$args) was added to \WP_Upgrader_Skin::feedback().
* We need to remove all calls to *Skin::feedback() method, as we can't override it in own Skin
* without breaking support for PHP 5.3-5.5.
*
* @internal Please do not use this class outside of core WPForms development. May be removed at any time.
*
* @since 1.7.1
*/
class PluginsInstallUpgrader extends \Plugin_Upgrader {
/**
* Run an upgrade/installation.
*
* Attempts to download the package (if it is not a local file), unpack it, and
* install it in the destination folder.
*
* @since 2.8.0
*
* @param array $options {
* Array or string of arguments for upgrading/installing a package.
*
* @type string $package The full path or URI of the package to install.
* Default empty.
* @type string $destination The full path to the destination folder.
* Default empty.
* @type bool $clear_destination Whether to delete any files already in the
* destination folder. Default false.
* @type bool $clear_working Whether to delete the files form the working
* directory after copying to the destination.
* Default false.
* @type bool $abort_if_destination_exists Whether to abort the installation if the destination
* folder already exists. When true, `$clear_destination`
* should be false. Default true.
* @type bool $is_multi Whether this run is one of multiple upgrade/installation
* actions being performed in bulk. When true, the skin
* WP_Upgrader::header() and WP_Upgrader::footer()
* aren't called. Default false.
* @type array $hook_extra Extra arguments to pass to the filter hooks called by
* WP_Upgrader::run().
* }
* @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error,
* or false if unable to connect to the filesystem.
*/
public function run( $options ) {
$defaults = array(
'package' => '', // Please always pass this.
'destination' => '', // And this
'clear_destination' => false,
'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
'clear_working' => true,
'is_multi' => false,
'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
);
$options = wp_parse_args( $options, $defaults );
/**
* Filters the package options before running an update.
*
* See also {@see 'upgrader_process_complete'}.
*
* @since 4.3.0
*
* @param array $options {
* Options used by the upgrader.
*
* @type string $package Package for update.
* @type string $destination Update location.
* @type bool $clear_destination Clear the destination resource.
* @type bool $clear_working Clear the working resource.
* @type bool $abort_if_destination_exists Abort if the Destination directory exists.
* @type bool $is_multi Whether the upgrader is running multiple times.
* @type array $hook_extra {
* Extra hook arguments.
*
* @type string $action Type of action. Default 'update'.
* @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
* @type bool $bulk Whether the update process is a bulk update. Default true.
* @type string $plugin Path to the plugin file relative to the plugins directory.
* @type string $theme The stylesheet or template name of the theme.
* @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme',
* or 'core'.
* @type object $language_update The language pack update offer.
* }
* }
*/
$options = apply_filters( 'upgrader_package_options', $options );
if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times
$this->skin->header();
}
// Connect to the Filesystem first.
$res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
// Mainly for non-connected filesystem.
if ( ! $res ) {
if ( ! $options['is_multi'] ) {
$this->skin->footer();
}
return false;
}
$this->skin->before();
if ( is_wp_error( $res ) ) {
$this->skin->error( $res );
$this->skin->after();
if ( ! $options['is_multi'] ) {
$this->skin->footer();
}
return $res;
}
/*
* Download the package (Note, This just returns the filename
* of the file if the package is a local file)
*/
$download = $this->download_package( $options['package'], true );
// Allow for signature soft-fail.
// WARNING: This may be removed in the future.
if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {
// Don't output the 'no signature could be found' failure message for now.
if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) {
// Outout the failure error as a normal feedback, and not as an error:
//$this->skin->feedback( $download->get_error_message() );
// Report this failure back to WordPress.org for debugging purposes.
wp_version_check(
array(
'signature_failure_code' => $download->get_error_code(),
'signature_failure_data' => $download->get_error_data(),
)
);
}
// Pretend this error didn't happen.
$download = $download->get_error_data( 'softfail-filename' );
}
if ( is_wp_error( $download ) ) {
$this->skin->error( $download );
$this->skin->after();
if ( ! $options['is_multi'] ) {
$this->skin->footer();
}
return $download;
}
$delete_package = ( $download != $options['package'] ); // Do not delete a "local" file
// Unzips the file into a temporary directory.
$working_dir = $this->unpack_package( $download, $delete_package );
if ( is_wp_error( $working_dir ) ) {
$this->skin->error( $working_dir );
$this->skin->after();
if ( ! $options['is_multi'] ) {
$this->skin->footer();
}
return $working_dir;
}
// With the given options, this installs it to the destination directory.
$result = $this->install_package(
array(
'source' => $working_dir,
'destination' => $options['destination'],
'clear_destination' => $options['clear_destination'],
'abort_if_destination_exists' => $options['abort_if_destination_exists'],
'clear_working' => $options['clear_working'],
'hook_extra' => $options['hook_extra'],
)
);
$this->skin->set_result( $result );
if ( is_wp_error( $result ) ) {
$this->skin->error( $result );
//$this->skin->feedback( 'process_failed' );
} else {
// Installation succeeded.
//$this->skin->feedback( 'process_success' );
}
$this->skin->after();
if ( ! $options['is_multi'] ) {
/**
* Fires when the upgrader process is complete.
*
* See also {@see 'upgrader_package_options'}.
*
* @since 3.6.0
* @since 3.7.0 Added to WP_Upgrader::run().
* @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
*
* @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a
* Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
* @param array $hook_extra {
* Array of bulk item update data.
*
* @type string $action Type of action. Default 'update'.
* @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
* @type bool $bulk Whether the update process is a bulk update. Default true.
* @type array $plugins Array of the basename paths of the plugins' main files.
* @type array $themes The theme slugs.
* @type array $translations {
* Array of translations update data.
*
* @type string $language The locale the translation is for.
* @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'.
* @type string $slug Text domain the translation is for. The slug of a theme/plugin or
* 'default' for core translations.
* @type string $version The version of a theme, plugin, or core.
* }
* }
*/
do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );
$this->skin->footer();
}
return $result;
}
/**
* Toggle maintenance mode for the site.
*
* Creates/deletes the maintenance file to enable/disable maintenance mode.
*
* @since 2.8.0
*
* @global WP_Filesystem_Base $wp_filesystem Subclass
*
* @param bool $enable True to enable maintenance mode, false to disable.
*/
public function maintenance_mode( $enable = false ) {
global $wp_filesystem;
$file = $wp_filesystem->abspath() . '.maintenance';
if ( $enable ) {
//$this->skin->feedback( 'maintenance_start' );
// Create maintenance file to signal that we are upgrading
$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
$wp_filesystem->delete( $file );
$wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
} elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
//$this->skin->feedback( 'maintenance_end' );
$wp_filesystem->delete( $file );
}
}
/**
* Download a package.
*
* @since 2.8.0
* @since 5.5.0 Added the `$hook_extra` parameter.
*
* @param string $package The URI of the package. If this is the full path to an
* existing local file, it will be returned untouched.
* @param bool $check_signatures Whether to validate file signatures. Default false.
* @param array $hook_extra Extra arguments to pass to the filter hooks. Default empty array.
*
* @return string|WP_Error The full path to the downloaded package file, or a WP_Error object.
*/
public function download_package( $package, $check_signatures = false, $hook_extra = array() ) {
/**
* Filters whether to return the package.
*
* @since 3.7.0
* @since 5.5.0 Added the `$hook_extra` parameter.
*
* @param bool $reply Whether to bail without returning the package.
* Default false.
* @param string $package The package file name.
* @param WP_Upgrader $this The WP_Upgrader instance.
* @param array $hook_extra Extra arguments passed to hooked filters.
*/
$reply = apply_filters( 'upgrader_pre_download', false, $package, $this, $hook_extra );
if ( false !== $reply ) {
return $reply;
}
if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote?
return $package; //must be a local file..
}
if ( empty( $package ) ) {
return new WP_Error( 'no_package', $this->strings['no_package'] );
}
//$this->skin->feedback( 'downloading_package', $package );
$download_file = download_url( $package, 300, $check_signatures );
if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) {
return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
}
return $download_file;
}
/**
* Unpack a compressed package file.
*
* @since 2.8.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
*
* @param string $package Full path to the package file.
* @param bool $delete_package Optional. Whether to delete the package file after attempting
* to unpack it. Default true.
* @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure.
*/
public function unpack_package( $package, $delete_package = true ) {
global $wp_filesystem;
//$this->skin->feedback( 'unpack_package' );
$upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
//Clean up contents of upgrade directory beforehand.
$upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
if ( ! empty( $upgrade_files ) ) {
foreach ( $upgrade_files as $file ) {
$wp_filesystem->delete( $upgrade_folder . $file['name'], true );
}
}
// We need a working directory - Strip off any .tmp or .zip suffixes
$working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
// Clean up working directory
if ( $wp_filesystem->is_dir( $working_dir ) ) {
$wp_filesystem->delete( $working_dir, true );
}
// Unzip package to working directory
$result = unzip_file( $package, $working_dir );
// Once extracted, delete the package if required.
if ( $delete_package ) {
unlink( $package );
}
if ( is_wp_error( $result ) ) {
$wp_filesystem->delete( $working_dir, true );
if ( 'incompatible_archive' == $result->get_error_code() ) {
return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
}
return $result;
}
return $working_dir;
}
/**
* Install a package.
*
* Copies the contents of a package form a source directory, and installs them in
* a destination directory. Optionally removes the source. It can also optionally
* clear out the destination folder if it already exists.
*
* @since 2.8.0
*
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
* @global array $wp_theme_directories
*
* @param array|string $args {
* Optional. Array or string of arguments for installing a package. Default empty array.
*
* @type string $source Required path to the package source. Default empty.
* @type string $destination Required path to a folder to install the package in.
* Default empty.
* @type bool $clear_destination Whether to delete any files already in the destination
* folder. Default false.
* @type bool $clear_working Whether to delete the files form the working directory
* after copying to the destination. Default false.
* @type bool $abort_if_destination_exists Whether to abort the installation if
* the destination folder already exists. Default true.
* @type array $hook_extra Extra arguments to pass to the filter hooks called by
* WP_Upgrader::install_package(). Default empty array.
* }
*
* @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure.
*/
public function install_package( $args = array() ) {
global $wp_filesystem, $wp_theme_directories;
$defaults = array(
'source' => '', // Please always pass this
'destination' => '', // and this
'clear_destination' => false,
'clear_working' => false,
'abort_if_destination_exists' => true,
'hook_extra' => array(),
);
$args = wp_parse_args( $args, $defaults );
// These were previously extract()'d.
$source = $args['source'];
$destination = $args['destination'];
$clear_destination = $args['clear_destination'];
set_time_limit( 300 );
if ( empty( $source ) || empty( $destination ) ) {
return new WP_Error( 'bad_request', $this->strings['bad_request'] );
}
//$this->skin->feedback( 'installing_package' );
/**
* Filters the install response before the installation has started.
*
* Returning a truthy value, or one that could be evaluated as a WP_Error
* will effectively short-circuit the installation, returning that value
* instead.
*
* @since 2.8.0
*
* @param bool|WP_Error $response Response.
* @param array $hook_extra Extra arguments passed to hooked filters.
*/
$res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );
if ( is_wp_error( $res ) ) {
return $res;
}
//Retain the Original source and destinations
$remote_source = $args['source'];
$local_destination = $destination;
$source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) );
$remote_destination = $wp_filesystem->find_folder( $local_destination );
//Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents.
$source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] );
} elseif ( count( $source_files ) == 0 ) {
return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files?
} else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
$source = trailingslashit( $args['source'] );
}
/**
* Filters the source file location for the upgrade package.
*
* @since 2.8.0
* @since 4.4.0 The $hook_extra parameter became available.
*
* @param string $source File source location.
* @param string $remote_source Remote file source location.
* @param WP_Upgrader $this WP_Upgrader instance.
* @param array $hook_extra Extra arguments passed to hooked filters.
*/
$source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );
if ( is_wp_error( $source ) ) {
return $source;
}
// Has the source location changed? If so, we need a new source_files list.
if ( $source !== $remote_source ) {
$source_files = array_keys( $wp_filesystem->dirlist( $source ) );
}
/*
* Protection against deleting files in any important base directories.
* Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
* destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
* to copy the directory into the directory, whilst they pass the source
* as the actual files to copy.
*/
$protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
if ( is_array( $wp_theme_directories ) ) {
$protected_directories = array_merge( $protected_directories, $wp_theme_directories );
}
if ( in_array( $destination, $protected_directories ) ) {
$remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
$destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
}
if ( $clear_destination ) {
// We're going to clear the destination if there's something there.
//$this->skin->feedback( 'remove_old' );
$removed = $this->clear_destination( $remote_destination );
/**
* Filters whether the upgrader cleared the destination.
*
* @since 2.8.0
*
* @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure
* @param string $local_destination The local package destination.
* @param string $remote_destination The remote package destination.
* @param array $hook_extra Extra arguments passed to hooked filters.
*/
$removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
if ( is_wp_error( $removed ) ) {
return $removed;
}
} elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) {
//If we're not clearing the destination folder and something exists there already, Bail.
//But first check to see if there are actually any files in the folder.
$_files = $wp_filesystem->dirlist( $remote_destination );
if ( ! empty( $_files ) ) {
$wp_filesystem->delete( $remote_source, true ); //Clear out the source files.
return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination );
}
}
//Create destination if needed
if ( ! $wp_filesystem->exists( $remote_destination ) ) {
if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );
}
}
// Copy new version of item into place.
$result = copy_dir( $source, $remote_destination );
if ( is_wp_error( $result ) ) {
if ( $args['clear_working'] ) {
$wp_filesystem->delete( $remote_source, true );
}
return $result;
}
//Clear the Working folder?
if ( $args['clear_working'] ) {
$wp_filesystem->delete( $remote_source, true );
}
$destination_name = basename( str_replace( $local_destination, '', $destination ) );
if ( '.' == $destination_name ) {
$destination_name = '';
}
$this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );
/**
* Filters the installation response after the installation has finished.
*
* @since 2.8.0
*
* @param bool $response Installation response.
* @param array $hook_extra Extra arguments passed to hooked filters.
* @param array $result Installation result data.
*/
$res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result );
if ( is_wp_error( $res ) ) {
$this->result = $res;
return $res;
}
//Bombard the calling function will all the info which we've just used.
return $this->result;
}
}

View File

@@ -2,6 +2,7 @@
namespace WPMailSMTP\Admin;
use Plugin_Upgrader;
use WPMailSMTP\Admin\Pages\TestTab;
use WPMailSMTP\Connect;
use WPMailSMTP\Helpers\Helpers;
@@ -81,7 +82,7 @@ class SetupWizard {
isset( $_GET['page'] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
Area::SLUG . '-setup-wizard' === $_GET['page'] && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$this->should_setup_wizard_load() &&
current_user_can( 'manage_options' )
current_user_can( wp_mail_smtp()->get_capability_manage_options() )
)
) {
return;
@@ -97,6 +98,10 @@ class SetupWizard {
// Remove an action in the Gutenberg plugin ( not core Gutenberg ) which throws an error.
remove_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' );
// Remove hooks for deprecated functions in WordPress 6.4.0.
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_action( 'admin_head', 'wp_admin_bar_header' );
$this->load_setup_wizard();
}
@@ -155,7 +160,7 @@ class SetupWizard {
return;
}
add_submenu_page( '', '', '', 'manage_options', Area::SLUG . '-setup-wizard', '' );
add_submenu_page( '', '', '', wp_mail_smtp()->get_capability_manage_options(), Area::SLUG . '-setup-wizard', '' );
}
/**
@@ -543,7 +548,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have permission to change options for this WP site!', 'wp-mail-smtp' ) );
}
@@ -561,7 +566,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have permission to change options for this WP site!', 'wp-mail-smtp' ) );
}
@@ -583,7 +588,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
@@ -625,7 +630,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have permission to change options for this WP site!', 'wp-mail-smtp' ) );
}
@@ -690,6 +695,7 @@ class SetupWizard {
*
* @since 2.6.0
* @since 3.10.0 Supply WPMS_AMAZONSES_DISPLAY_IDENTITIES constant value to control display of Amazon SES identity list.
* @since 3.11.0 Removed WPMS_AMAZONSES_DISPLAY_IDENTITIES constant handling.
*
* @return array
*/
@@ -710,10 +716,6 @@ class SetupWizard {
if ( $provider->get_slug() === 'gmail' ) {
$data['gmail']['redirect_uri'] = \WPMailSMTP\Providers\Gmail\Auth::get_oauth_redirect_url();
}
if ( $provider->get_slug() === 'amazonses' ) {
$data['amazonses']['display_identities'] = ! defined( 'WPMS_AMAZONSES_DISPLAY_IDENTITIES' ) || WPMS_AMAZONSES_DISPLAY_IDENTITIES === true;
}
}
return apply_filters( 'wp_mail_smtp_admin_setup_wizard_prepare_mailer_options', $data );
@@ -728,7 +730,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
@@ -738,7 +740,7 @@ class SetupWizard {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$settings = isset( $_POST['settings'] ) ? wp_slash( json_decode( wp_unslash( $_POST['settings'] ), true ) ) : [];
if ( empty( $mailer ) || empty( $settings ) ) {
if ( empty( $mailer ) ) {
wp_send_json_error();
}
@@ -749,7 +751,7 @@ class SetupWizard {
switch ( $mailer ) {
case 'gmail':
$auth = new \WPMailSMTP\Providers\Gmail\Auth();
$auth = wp_mail_smtp()->get_providers()->get_auth( 'gmail' );
if ( $auth->is_clients_saved() && $auth->is_auth_required() ) {
$data['oauth_url'] = $auth->get_auth_url();
@@ -771,7 +773,7 @@ class SetupWizard {
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
@@ -784,20 +786,11 @@ class SetupWizard {
switch ( $mailer ) {
case 'gmail':
$auth = new \WPMailSMTP\Providers\Gmail\Auth();
$auth = wp_mail_smtp()->get_providers()->get_auth( 'gmail' );
if ( $auth->is_clients_saved() && ! $auth->is_auth_required() ) {
$user_info = $auth->get_user_info();
$data['connected_email'] = $user_info['email'];
$data['possible_send_from_addresses'] = array_map(
function( $value ) {
return [
'value' => $value,
'label' => $value,
];
},
$auth->get_user_possible_send_from_addresses()
);
$user_info = $auth->get_user_info();
$data['connected_email'] = $user_info['email'];
}
break;
}
@@ -810,11 +803,11 @@ class SetupWizard {
*
* @since 2.6.0
*/
public function remove_oauth_connection() {
public function remove_oauth_connection() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
check_ajax_referer( 'wpms-admin-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
@@ -827,10 +820,21 @@ class SetupWizard {
$options = Options::init();
$old_opt = $options->get_all_raw();
foreach ( $old_opt[ $mailer ] as $key => $value ) {
// Unset everything except Client ID, Client Secret and Domain (for Zoho).
if ( ! in_array( $key, array( 'domain', 'client_id', 'client_secret' ), true ) ) {
unset( $old_opt[ $mailer ][ $key ] );
/*
* Since Gmail mailer uses the same settings array for both the custom app and One-Click Setup,
* we need to make sure we don't remove the wrong settings.
*/
if ( $mailer === 'gmail' ) {
unset( $old_opt[ $mailer ]['access_token'] );
unset( $old_opt[ $mailer ]['refresh_token'] );
unset( $old_opt[ $mailer ]['user_details'] );
unset( $old_opt[ $mailer ]['auth_code'] );
} else {
foreach ( $old_opt[ $mailer ] as $key => $value ) {
// Unset everything except Client ID, Client Secret and Domain (for Zoho).
if ( ! in_array( $key, [ 'domain', 'client_id', 'client_secret' ], true ) ) {
unset( $old_opt[ $mailer ][ $key ] );
}
}
}
@@ -868,8 +872,16 @@ class SetupWizard {
wp_send_json_error( esc_html__( 'Could not install the plugin. Plugin is not whitelisted.', 'wp-mail-smtp' ) );
}
$url = esc_url_raw( WP::admin_url( 'admin.php?page=' . Area::SLUG . '-setup-wizard' ) );
$url = esc_url_raw( WP::admin_url( 'admin.php?page=' . Area::SLUG . '-setup-wizard' ) );
/*
* The `request_filesystem_credentials` function will output a credentials form in case of failure.
* We don't want that, since it will break AJAX response. So just hide output with a buffer.
*/
ob_start();
// phpcs:ignore WPForms.Formatting.EmptyLineAfterAssigmentVariables.AddEmptyLine
$creds = request_filesystem_credentials( $url, '', false, false, null );
ob_end_clean();
// Check for file system permissions.
if ( false === $creds ) {
@@ -883,8 +895,11 @@ class SetupWizard {
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 );
// Import the plugin upgrader.
Helpers::include_plugin_upgrader();
// Create the plugin upgrader with our custom skin.
$installer = new PluginsInstallUpgrader( new PluginsInstallSkin() );
$installer = new Plugin_Upgrader( new PluginsInstallSkin() );
// Error check.
if ( ! method_exists( $installer, 'install' ) || empty( $slug ) ) {