File: /var/www/clients/client0/web20/web/wp-content/plugins/easy-wp-smtp/src/Core.php
<?php
namespace EasyWPSMTP;
use EasyWPSMTP\Admin\Area as AdminArea;
use EasyWPSMTP\Admin\DebugEvents\DebugEvents;
use EasyWPSMTP\Admin\Notifications;
use EasyWPSMTP\Migrations\Migrations;
use EasyWPSMTP\Providers\Loader as ProvidersLoader;
use EasyWPSMTP\Tasks\Tasks;
use Exception;
use ReflectionFunction;
/**
* Class Core to handle all plugin initialization.
*
* @since 2.0.0
*/
class Core {
/**
* URL to plugin directory.
*
* @since 2.0.0
*
* @var string Without trailing slash.
*/
public $plugin_url;
/**
* URL to Lite plugin assets directory.
*
* @since 2.0.0
*
* @var string Without trailing slash.
*/
public $assets_url;
/**
* Path to plugin directory.
*
* @since 2.0.0
*
* @var string Without trailing slash.
*/
public $plugin_path;
/**
* Core constructor.
*
* @since 2.0.0
*/
public function __construct() {
$this->plugin_url = rtrim( plugin_dir_url( __DIR__ ), '/\\' );
$this->assets_url = $this->plugin_url . '/assets';
$this->plugin_path = rtrim( plugin_dir_path( __DIR__ ), '/\\' );
if ( version_compare( phpversion(), '5.6', '<' ) ) {
add_action( 'admin_notices', 'easy_wp_smtp_insecure_php_version_notice' );
return;
}
// Finally, load all the plugin.
$this->hooks();
$this->init_early();
}
/**
* Assign all hooks to proper places.
*
* @since 2.0.0
*/
public function hooks() {
// Activation hook.
register_activation_hook( EasyWPSMTP_PLUGIN_FILE, [ $this, 'activate' ] );
// Redefine PHPMailer.
add_action( 'plugins_loaded', [ $this, 'get_processor' ] );
add_action( 'plugins_loaded', [ $this, 'replace_phpmailer' ] );
// Various notifications.
add_action( 'admin_init', [ $this, 'init_notifications' ] );
add_action( 'init', [ $this, 'init' ] );
// Initialize Action Scheduler tasks.
add_action( 'init', [ $this, 'get_tasks' ], 5 );
add_action( 'plugins_loaded', [ $this, 'get_migrations' ] );
add_action( 'plugins_loaded', [ $this, 'get_notifications' ] );
add_action( 'plugins_loaded', [ $this, 'get_connections_manager' ], 20 );
add_action( 'plugins_loaded', [ $this, 'get_wp_mail_initiator' ] );
}
/**
* Initial plugin actions.
*
* @since 2.0.0
*/
public function init() {
// Load translations just in case.
load_plugin_textdomain( 'easy-wp-smtp', false, plugin_basename( easy_wp_smtp()->plugin_path ) . '/assets/languages' );
/*
* Constantly check in admin area, that we don't need to upgrade DB.
* Do not wait for the `admin_init` hook, because some actions are already done
* on `plugins_loaded`, so migration has to be done before.
* We should not fire this in AJAX requests.
*/
if ( WP::in_wp_admin() ) {
$this->detect_conflicts();
}
// In admin area, regardless of AJAX or not AJAX request.
if ( is_admin() ) {
$this->get_admin();
// Register Debug Event hooks.
( new DebugEvents() )->hooks();
}
// Plugin admin area notices. Display to "admins" only.
if ( current_user_can( 'manage_options' ) ) {
add_action( 'admin_notices', array( '\EasyWPSMTP\WP', 'display_admin_notices' ) );
add_action( 'admin_notices', array( $this, 'display_general_notices' ) );
}
}
/**
* Get/Load the Tasks code of the plugin.
*
* @since 2.0.0
*
* @return Tasks
*/
public function get_tasks() {
static $tasks = null;
if ( is_null( $tasks ) ) {
/**
* Filter the tasks class name.
*
* @since 2.0.0
*
* @param Tasks $tasks_class_name The tasks class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_tasks', Tasks::class );
$tasks = new $class_name();
if ( method_exists( $tasks, 'init' ) ) {
$tasks->init();
}
}
return $tasks;
}
/**
* Get/Load the Migrations code of the plugin.
*
* @since 2.0.0
*
* @return Migrations
*/
public function get_migrations() {
static $migrations = null;
if ( is_null( $migrations ) ) {
/**
* Filter the migrations class name.
*
* @since 2.0.0
*
* @param Migrations $migrations_class_name The migrations class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_migrations', Migrations::class );
$migrations = new $class_name();
if ( method_exists( $migrations, 'hooks' ) ) {
$migrations->hooks();
}
}
return $migrations;
}
/**
* This method allows to overwrite certain core WP functions, because it's fired:
* - after `muplugins_loaded` hook,
* - before WordPress own `wp-includes/pluggable.php` file include,
* - before `plugin_loaded` and `plugins_loaded` hooks.
*
* @since 2.0.0
*/
protected function init_early() {
// Action Scheduler requires a special early loading procedure.
$this->load_action_scheduler();
$files = (array) apply_filters( 'easy_wp_smtp_core_init_early_include_files', [] );
foreach ( $files as $file ) {
$path = $this->plugin_path . '/' . $file;
if ( is_readable( $path ) ) {
/** @noinspection PhpIncludeInspection */
include_once $path;
}
}
// Include deprecated classes.
require_once $this->plugin_path . '/inc/deprecated/class-easywpsmtp.php';
}
/**
* Load the plugin core processor.
*
* @since 2.0.0
*
* @return Processor
*/
public function get_processor() {
static $processor = null;
if ( is_null( $processor ) ) {
/**
* Filter the processor class name.
*
* @since 2.0.0
*
* @param Processor $processor_class_name The processor class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_processor', Processor::class );
$processor = new $class_name();
if ( method_exists( $processor, 'hooks' ) ) {
$processor->hooks();
}
}
return $processor;
}
/**
* Load the plugin admin area.
*
* @since 2.0.0
*
* @return AdminArea
*/
public function get_admin() {
static $admin = null;
if ( is_null( $admin ) ) {
/**
* Filter the admin class name.
*
* @since 2.0.0
*
* @param AdminArea $admin_class_name The admin class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_admin', AdminArea::class );
$admin = new $class_name();
}
return $admin;
}
/**
* Load the plugin providers loader.
*
* @since 2.0.0
*
* @return ProvidersLoader
*/
public function get_providers() {
static $providers = null;
if ( is_null( $providers ) ) {
/**
* Filter the providers loader class name.
*
* @since 2.0.0
*
* @param ProvidersLoader $providers_class_name The providers loader class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_providers', ProvidersLoader::class );
$providers = new $class_name();
}
return $providers;
}
/**
* Display various notifications to a user
*
* @since 2.0.0
*/
public function init_notifications() {
// Old PHP version notification.
if (
version_compare( phpversion(), '5.6', '<' ) &&
is_super_admin() &&
(
isset( $GLOBALS['pagenow'] ) &&
$GLOBALS['pagenow'] === 'index.php'
)
) {
WP::add_admin_notice(
sprintf(
wp_kses( /* translators: %1$s - Easy WP SMTP plugin name; %2$s - EasyWPSMTP.com URL to a related doc. */
__( 'Your site is running an outdated version of PHP that is no longer supported and may cause issues with %1$s. <a href="%2$s" target="_blank" rel="noopener noreferrer">Read more</a> for additional information.', 'easy-wp-smtp' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
)
),
'<strong>Easy WP SMTP</strong>',
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( easy_wp_smtp()->get_utm_url( 'https://easywpsmtp.com/docs/supported-php-versions-for-easy-wp-smtp/', [ 'medium' => 'Admin Notice', 'content' => 'Upgrade PHP Recommendation' ] ) )
) .
'<br><br><em>' .
wp_kses(
__( '<strong>Please Note:</strong> Support for PHP 5.5 will be discontinued in 2021. After this, if no further action is taken, Easy WP SMTP functionality will be disabled.', 'easy-wp-smtp' ),
array(
'strong' => array(),
'em' => array(),
)
) .
'</em>',
WP::ADMIN_NOTICE_ERROR,
false
);
}
}
/**
* Display all debug mail-delivery related notices.
*
* @since 2.0.0
*/
public static function display_general_notices() {
if ( easy_wp_smtp()->is_blocked() ) {
?>
<div class="notice <?php echo esc_attr( WP::ADMIN_NOTICE_ERROR ); ?>">
<p>
<?php
$notices[] = sprintf(
/* translators: %s - plugin name and its version. */
__( '<strong>EMAILING DISABLED:</strong> The %s is currently blocking all emails from being sent.', 'easy-wp-smtp' ),
esc_html( 'Easy WP SMTP v' . EasyWPSMTP_PLUGIN_VERSION )
);
if ( Options::init()->is_const_defined( 'general', 'do_not_send' ) ) {
$notices[] = sprintf(
/* translators: %1$s - constant name; %2$s - constant value. */
__( 'To send emails, change the value of the %1$s constant to %2$s.', 'easy-wp-smtp' ),
'<code>EASY_WP_SMTP_DO_NOT_SEND</code>',
'<code>false</code>'
);
} else {
$notices[] = sprintf(
/* translators: %s - plugin Misc settings page URL. */
__( 'To send emails, go to plugin <a href="%s">Misc settings</a> and disable the "Do Not Send" option.', 'easy-wp-smtp' ),
esc_url( add_query_arg( 'tab', 'misc', easy_wp_smtp()->get_admin()->get_admin_page_url() ) )
);
}
if (
easy_wp_smtp()->get_admin()->is_admin_page( 'tools' ) &&
(
! isset( $_GET['tab'] ) ||
( isset( $_GET['tab'] ) && $_GET['tab'] === 'test' )
)
) {
$notices[] = esc_html__( 'If you create a test email on this page, it will still be sent.', 'easy-wp-smtp' );
}
echo wp_kses_post( implode( ' ', $notices ) );
?>
</p>
</div>
<?php
return;
}
if ( easy_wp_smtp()->get_admin()->is_admin_page() ) {
easy_wp_smtp()->wp_mail_function_incorrect_location_notice();
}
if ( easy_wp_smtp()->get_admin()->is_error_delivery_notice_enabled() ) {
$screen = get_current_screen();
// Skip the error notice if not on plugin page.
if (
is_object( $screen ) &&
strpos( $screen->id, 'page_easy-wp-smtp' ) === false
) {
return;
}
$notice = apply_filters(
'easy_wp_smtp_core_display_general_notices_email_delivery_error_notice',
Debug::get_last()
);
if ( ! empty( $notice ) ) {
?>
<div class="notice <?php echo esc_attr( WP::ADMIN_NOTICE_ERROR ); ?>">
<p>
<?php
echo wp_kses(
__( '<strong>Heads up!</strong> The last email your site attempted to send was unsuccessful.', 'easy-wp-smtp' ),
[
'strong' => [],
]
);
?>
</p>
<blockquote>
<pre><?php echo wp_kses_post( $notice ); ?></pre>
</blockquote>
<p>
<?php
if ( ! easy_wp_smtp()->get_admin()->is_admin_page() ) {
printf(
wp_kses( /* translators: %s - plugin admin page URL. */
__( 'Please review your Easy WP SMTP settings in <a href="%s">plugin admin area</a>.' ) . ' ',
array(
'a' => array(
'href' => array(),
),
)
),
esc_url( easy_wp_smtp()->get_admin()->get_admin_page_url() )
);
}
printf(
wp_kses( /* translators: %s - URL to the debug events page. */
__( 'For more details please try running an Email Test or reading the latest <a href="%s">error event</a>.' ),
[
'a' => [
'href' => [],
],
]
),
esc_url( DebugEvents::get_page_url() )
);
?>
</p>
<?php
echo wp_kses(
apply_filters(
'easy_wp_smtp_core_display_general_notices_email_delivery_error_notice_footer',
''
),
[
'p' => [],
'a' => [
'href' => [],
'target' => [],
'class' => [],
'rel' => [],
],
]
);
?>
</div>
<?php
}
}
}
/**
* Detect if there are plugins activated that will cause a conflict.
*
* @since 2.0.0
*/
public function detect_conflicts() {
// Display only for those who can actually deactivate plugins.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$conflicts = new Conflicts();
if ( $conflicts->is_detected() ) {
$conflicts->notify();
}
}
/**
* Init the \PHPMailer replacement.
*
* @since 2.0.0
*
* @return MailCatcherInterface
*/
public function replace_phpmailer() {
global $phpmailer;
return $this->replace_w_fake_phpmailer( $phpmailer );
}
/**
* Overwrite default PhpMailer with our MailCatcher.
*
* @since 2.0.0
*
* @param null $obj PhpMailer object to override with own implementation.
*
* @return MailCatcherInterface
*/
protected function replace_w_fake_phpmailer( &$obj = null ) {
$obj = $this->generate_mail_catcher( true );
return $obj;
}
/**
* What to do on plugin activation.
*
* @since 2.0.0
*/
public function activate() {
// Store the plugin version when initial install occurred.
add_option( 'easy_wp_smtp_initial_version', EasyWPSMTP_PLUGIN_VERSION, '', false );
// Store the plugin version activated to reference with upgrades.
update_option( 'easy_wp_smtp_version', EasyWPSMTP_PLUGIN_VERSION, false );
// Don't save default options after upgrade from 1.x version.
if ( empty( get_option( 'swpsmtp_options' ) ) ) {
// Save default options, only once.
Options::init()->set( Options::get_defaults(), true );
}
/**
* Store the timestamp of first plugin activation.
*
* @since 2.0.0
*/
add_option( 'easy_wp_smtp_activated_time', time(), '', false );
}
/**
* Get UTM URL.
*
* @since 2.0.0
*
* @param string $url Base url.
* @param array|string $utm Array of UTM params, or if string provided - utm_content URL parameter.
*
* @return string
*/
public function get_utm_url( $url, $utm ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
// Defaults.
$source = 'WordPress';
$medium = 'plugin-settings';
$campaign = 'liteplugin';
$content = 'general';
if ( is_array( $utm ) ) {
if ( isset( $utm['source'] ) ) {
$source = $utm['source'];
}
if ( isset( $utm['medium'] ) ) {
$medium = $utm['medium'];
}
if ( isset( $utm['campaign'] ) ) {
$campaign = $utm['campaign'];
}
if ( isset( $utm['content'] ) ) {
$content = $utm['content'];
}
} elseif ( is_string( $utm ) ) {
$content = $utm;
}
$query_args = [
'utm_source' => esc_attr( rawurlencode( $source ) ),
'utm_medium' => esc_attr( rawurlencode( $medium ) ),
'utm_campaign' => esc_attr( rawurlencode( $campaign ) ),
];
if ( ! empty( $content ) ) {
$query_args['utm_content'] = esc_attr( rawurlencode( $content ) );
}
return add_query_arg( $query_args, $url );
}
/**
* Whether the emailing functionality is blocked, with either an option or a constatnt.
*
* @since 2.0.0
*
* @return bool
*/
public function is_blocked() {
return (bool) Options::init()->get( 'general', 'do_not_send' );
}
/**
* Require the action scheduler in an early plugins_loaded hook (-10).
*
* @see https://actionscheduler.org/usage/#load-order
*
* @since 2.0.0
*/
public function load_action_scheduler() {
require_once $this->plugin_path . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
}
/**
* Generate the correct MailCatcher object based on the PHPMailer version used in WP.
*
* Also conditionally require the needed class files.
*
* @see https://make.wordpress.org/core/2020/07/01/external-library-updates-in-wordpress-5-5-call-for-testing/
*
* @since 2.0.0
*
* @param bool $exceptions True if external exceptions should be thrown.
*
* @return MailCatcherInterface
*/
public function generate_mail_catcher( $exceptions = null ) {
$is_old_version = version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' );
if ( $is_old_version ) {
if ( ! class_exists( '\PHPMailer', false ) ) {
require_once ABSPATH . WPINC . '/class-phpmailer.php';
}
$class_name = MailCatcher::class;
} else {
if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) {
require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
}
if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) {
require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
}
if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) {
require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
}
$class_name = MailCatcherV6::class;
}
/**
* Filters MailCatcher class name.
*
* @since 2.0.0
*
* @param string $mail_catcher_class_name The MailCatcher class name.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_generate_mail_catcher', $class_name );
$mail_catcher = new $class_name( $exceptions );
if ( $is_old_version ) {
$mail_catcher::$validator = static function ( $email ) {
return (bool) is_email( $email );
};
}
return $mail_catcher;
}
/**
* Check if the passed object is a valid PHPMailer object.
*
* @since 2.0.0
*
* @param object $phpmailer A potential PHPMailer object to be tested.
*
* @return bool
*/
public function is_valid_phpmailer( $phpmailer ) {
return $phpmailer instanceof MailCatcherInterface ||
$phpmailer instanceof \PHPMailer ||
$phpmailer instanceof \PHPMailer\PHPMailer\PHPMailer;
}
/**
* Load the plugin admin notifications functionality and initializes it.
*
* @since 2.0.0
*
* @return Notifications
*/
public function get_notifications() {
static $notifications = null;
if ( is_null( $notifications ) ) {
/**
* Filter the notifications class name.
*
* @since 2.0.0
*
* @param Notifications $notifications_class_name The notifications class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_notifications', Notifications::class );
$notifications = new $class_name();
if ( method_exists( $notifications, 'init' ) ) {
$notifications->init();
}
}
return $notifications;
}
/**
* Prepare the HTML output for a plugin loader/spinner.
*
* @since 2.0.0
*
* @param string $color The color of the loader ('', 'blue' or 'white'), where '' is default orange.
* @param string $size The size of the loader ('lg', 'md', 'sm').
*
* @return string
*/
public function prepare_loader( $color = '', $size = 'md' ) {
$svg_name = 'loading';
if ( in_array( $color, [ 'blue', 'white' ], true ) ) {
$svg_name .= '-' . $color;
}
if ( ! in_array( $size, [ 'lg', 'md', 'sm' ], true ) ) {
$size = 'md';
}
return '<img src="' . esc_url( $this->plugin_url . '/assets/images/loaders/' . $svg_name . '.svg' ) . '" alt="' . esc_attr__( 'Loading', 'easy-wp-smtp' ) . '" class="easy-wp-smtp-loading easy-wp-smtp-loading-' . $size . '">';
}
/**
* Get connections manager.
*
* @since 2.0.0
*
* @return ConnectionsManager
*/
public function get_connections_manager() {
static $connections_manager = null;
if ( is_null( $connections_manager ) ) {
/**
* Filter the connections manager class name.
*
* @since 2.0.0
*
* @param ConnectionsManager $connections_manager_class_name The connections manager class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_connections_manager', ConnectionsManager::class );
$connections_manager = new $class_name();
if ( method_exists( $connections_manager, 'hooks' ) ) {
$connections_manager->hooks();
}
}
return $connections_manager;
}
/**
* Get the `wp_mail` function initiator.
*
* @since 2.0.0
*
* @return WPMailInitiator
*/
public function get_wp_mail_initiator() {
static $wp_mail_initiator = null;
if ( is_null( $wp_mail_initiator ) ) {
/**
* Filter the `wp_mail` function initiator class name.
*
* @since 2.0.0
*
* @param WPMailInitiator $wp_mail_initiator_class_name The `wp_mail` function initiator class name to be instantiated.
*/
$class_name = apply_filters( 'easy_wp_smtp_core_get_wp_mail_initiator', WPMailInitiator::class );
$wp_mail_initiator = new $class_name();
if ( method_exists( $wp_mail_initiator, 'hooks' ) ) {
$wp_mail_initiator->hooks();
}
}
return $wp_mail_initiator;
}
/**
* Detect incorrect `wp_mail` function location and display warning.
*
* @since 2.0.0
*/
private function wp_mail_function_incorrect_location_notice() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
/**
* Filters whether to display incorrect `wp_mail` function location warning.
*
* @since 2.0.0
*
* @param bool $display Whether to display incorrect `wp_mail` function location warning.
*/
$display_notice = apply_filters( 'easy_wp_smtp_core_wp_mail_function_incorrect_location_notice', true );
if ( ! $display_notice || ! defined( 'ABSPATH' ) || ! defined( 'WPINC' ) ) {
return;
}
try {
$wp_mail_reflection = new ReflectionFunction( 'wp_mail' );
$wp_mail_filepath = $wp_mail_reflection->getFileName();
$separator = defined( 'DIRECTORY_SEPARATOR' ) ? DIRECTORY_SEPARATOR : '/';
$wp_mail_original_filepath = ABSPATH . WPINC . $separator . 'pluggable.php';
if ( str_replace( '\\', '/', $wp_mail_filepath ) === str_replace( '\\', '/', $wp_mail_original_filepath ) ) {
return;
}
if ( strpos( $wp_mail_filepath, WPINC . $separator . 'pluggable.php' ) !== false ) {
return;
}
$conflict = WP::get_initiator( $wp_mail_filepath );
$message = esc_html__( 'Easy WP SMTP has detected incorrect "wp_mail" function location. Usually, this means that emails will not be sent successfully!', 'easy-wp-smtp' );
if ( $conflict['type'] === 'plugin' ) {
$message .= '<br><br>' . sprintf(
/* translators: %s - plugin name. */
esc_html__( 'It looks like the "%s" plugin is overwriting the "wp_mail" function. Please reach out to the plugin developer on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with Easy WP SMTP.', 'easy-wp-smtp' ),
esc_html( $conflict['name'] )
);
} elseif ( $conflict['type'] === 'mu-plugin' ) {
$message .= '<br><br>' . sprintf(
/* translators: %s - must-use plugin name. */
esc_html__( 'It looks like the "%s" must-use plugin is overwriting the "wp_mail" function. Please reach out to your hosting provider on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with Easy WP SMTP.', 'easy-wp-smtp' ),
esc_html( $conflict['name'] )
);
} elseif ( $wp_mail_filepath === ABSPATH . 'wp-config.php' ) {
$message .= '<br><br>' . esc_html__( 'It looks like it\'s overwritten in the "wp-config.php" file. Please reach out to your hosting provider on how to disable or remove the "wp_mail" function overwrite to prevent conflicts with Easy WP SMTP.', 'easy-wp-smtp' );
}
$message .= '<br><br>' . sprintf(
/* translators: %s - path. */
esc_html__( 'Current function path: %s', 'easy-wp-smtp' ),
$wp_mail_filepath . ':' . $wp_mail_reflection->getStartLine()
);
printf(
'<div class="notice %1$s"><p>%2$s</p></div>',
esc_attr( WP::ADMIN_NOTICE_ERROR ),
wp_kses( $message, [ 'br' => [] ] )
);
} catch ( Exception $e ) {
return;
}
}
}