264 lines
6.9 KiB
PHP
264 lines
6.9 KiB
PHP
<?php
|
|||
|
|
/**
|
||
|
|
* Plugin Name: WooCommerce Email Discount Manager
|
||
|
|
* Plugin URI: https://example.com/
|
||
|
|
* Description: Apply discounts and show/hide shipping methods based on the customer's email address (full address, domain or partial match).
|
||
|
|
* Version: 1.3.1
|
||
|
|
* Author: WEDSMP
|
||
|
|
* License: GPL-2.0-or-later
|
||
|
|
* Text Domain: wc-email-discount
|
||
|
|
* Requires at least: 5.8
|
||
|
|
* Requires PHP: 7.4
|
||
|
|
* WC requires at least: 6.0
|
||
|
|
* Requires Plugins: woocommerce
|
||
|
|
*/
|
||
|
|
|
||
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
||
|
|
exit;
|
||
|
|
}
|
||
|
|
|
||
|
|
define( 'WC_EDM_VERSION', '1.3.1' );
|
||
|
|
define( 'WC_EDM_PLUGIN_FILE', __FILE__ );
|
||
|
|
define( 'WC_EDM_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
||
|
|
define( 'WC_EDM_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Main plugin class (singleton).
|
||
|
|
*/
|
||
|
|
final class WC_Email_Discount_Manager {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Singleton instance.
|
||
|
|
*
|
||
|
|
* @var WC_Email_Discount_Manager|null
|
||
|
|
*/
|
||
|
|
private static $instance = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Admin controller.
|
||
|
|
*
|
||
|
|
* @var WC_EDM_Admin|null
|
||
|
|
*/
|
||
|
|
public $admin = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Frontend controller.
|
||
|
|
*
|
||
|
|
* @var WC_EDM_Frontend|null
|
||
|
|
*/
|
||
|
|
public $frontend = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* REST API controller.
|
||
|
|
*
|
||
|
|
* @var WC_EDM_REST_API|null
|
||
|
|
*/
|
||
|
|
public $rest_api = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Audit log controller.
|
||
|
|
*
|
||
|
|
* @var WC_EDM_Audit_Log|null
|
||
|
|
*/
|
||
|
|
public $audit_log = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Class files that could not be loaded.
|
||
|
|
*
|
||
|
|
* A plugin upgrade replaces files one by one, so a request landing
|
||
|
|
* mid-copy can see an incomplete plugin folder. Tracking what is missing
|
||
|
|
* lets the plugin degrade instead of taking the whole screen down.
|
||
|
|
*
|
||
|
|
* @var string[]
|
||
|
|
*/
|
||
|
|
private $missing_files = array();
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the singleton instance.
|
||
|
|
*
|
||
|
|
* @return WC_Email_Discount_Manager
|
||
|
|
*/
|
||
|
|
public static function instance() {
|
||
|
|
if ( null === self::$instance ) {
|
||
|
|
self::$instance = new self();
|
||
|
|
}
|
||
|
|
return self::$instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Constructor. Private — use instance().
|
||
|
|
*/
|
||
|
|
private function __construct() {
|
||
|
|
add_action( 'plugins_loaded', array( $this, 'init' ) );
|
||
|
|
add_action( 'before_woocommerce_init', array( $this, 'declare_wc_compatibility' ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Prevent cloning.
|
||
|
|
*/
|
||
|
|
private function __clone() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Prevent unserializing.
|
||
|
|
*/
|
||
|
|
public function __wakeup() {
|
||
|
|
_doing_it_wrong( __FUNCTION__, 'Unserializing is not allowed.', '1.0.0' );
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Bootstrap once all plugins are loaded.
|
||
|
|
*/
|
||
|
|
public function init() {
|
||
|
|
if ( ! class_exists( 'WooCommerce' ) ) {
|
||
|
|
add_action( 'admin_notices', array( $this, 'woocommerce_missing_notice' ) );
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
load_plugin_textdomain( 'wc-email-discount', false, dirname( plugin_basename( WC_EDM_PLUGIN_FILE ) ) . '/languages' );
|
||
|
|
|
||
|
|
$this->includes();
|
||
|
|
|
||
|
|
if ( ! empty( $this->missing_files ) ) {
|
||
|
|
add_action( 'admin_notices', array( $this, 'incomplete_install_notice' ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
// Everything else builds on these two, so without them the plugin
|
||
|
|
// stays dormant and shows the notice instead of erroring out.
|
||
|
|
if ( ! class_exists( 'WC_EDM_DB' ) || ! class_exists( 'WC_EDM_Helpers' ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Upgrade the DB schema after plugin updates that skip re-activation.
|
||
|
|
add_action( 'init', array( 'WC_EDM_DB', 'maybe_upgrade' ), 5 );
|
||
|
|
|
||
|
|
if ( is_admin() && class_exists( 'WC_EDM_Admin' ) ) {
|
||
|
|
$this->admin = new WC_EDM_Admin();
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( class_exists( 'WC_EDM_Frontend' ) ) {
|
||
|
|
$this->frontend = new WC_EDM_Frontend();
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( class_exists( 'WC_EDM_Audit_Log' ) ) {
|
||
|
|
$this->audit_log = new WC_EDM_Audit_Log();
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( class_exists( 'WC_EDM_REST_API' ) ) {
|
||
|
|
$this->rest_api = new WC_EDM_REST_API();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Warn that the plugin folder is incomplete.
|
||
|
|
*/
|
||
|
|
public function incomplete_install_notice() {
|
||
|
|
if ( ! current_user_can( 'activate_plugins' ) ) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
echo '<div class="notice notice-error"><p>';
|
||
|
|
echo esc_html__( 'WooCommerce Email Discount Manager could not load all of its files, so some features are unavailable. If you just updated the plugin, reload this page — the upload may still have been in progress. If the warning persists, upload the plugin again.', 'wc-email-discount' );
|
||
|
|
echo '</p><p><code>';
|
||
|
|
echo implode( '</code>, <code>', array_map( 'esc_html', $this->missing_files ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||
|
|
echo '</code></p></div>';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Load class files.
|
||
|
|
*/
|
||
|
|
private function includes() {
|
||
|
|
$files = array(
|
||
|
|
'includes/class-db.php',
|
||
|
|
'includes/class-helpers.php',
|
||
|
|
'includes/class-frontend.php',
|
||
|
|
'includes/class-audit-log.php',
|
||
|
|
'includes/class-rate-limiter.php',
|
||
|
|
'includes/class-rest-api.php',
|
||
|
|
);
|
||
|
|
|
||
|
|
if ( is_admin() ) {
|
||
|
|
$files = array_merge(
|
||
|
|
$files,
|
||
|
|
array(
|
||
|
|
'includes/class-admin.php',
|
||
|
|
'includes/class-admin-groups.php',
|
||
|
|
'includes/class-admin-emails.php',
|
||
|
|
'includes/class-admin-shipping.php',
|
||
|
|
'includes/class-admin-audit.php',
|
||
|
|
)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ( $files as $file ) {
|
||
|
|
$path = WC_EDM_PLUGIN_DIR . $file;
|
||
|
|
|
||
|
|
// A missing file is recorded rather than fatal, so a half-copied
|
||
|
|
// upgrade cannot take down wp-admin.
|
||
|
|
if ( is_readable( $path ) ) {
|
||
|
|
require_once $path;
|
||
|
|
} else {
|
||
|
|
$this->missing_files[] = $file;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Declare compatibility with WooCommerce HPOS.
|
||
|
|
*/
|
||
|
|
public function declare_wc_compatibility() {
|
||
|
|
if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
|
||
|
|
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', WC_EDM_PLUGIN_FILE, true );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Admin notice shown when WooCommerce is not active.
|
||
|
|
*/
|
||
|
|
public function woocommerce_missing_notice() {
|
||
|
|
echo '<div class="notice notice-error"><p>';
|
||
|
|
esc_html_e( 'WooCommerce Email Discount Manager requires WooCommerce to be installed and active.', 'wc-email-discount' );
|
||
|
|
echo '</p></div>';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Plugin activation: verify WooCommerce and create database tables.
|
||
|
|
*/
|
||
|
|
public static function activate() {
|
||
|
|
$active_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins', array() ) );
|
||
|
|
|
||
|
|
if ( ! class_exists( 'WooCommerce' ) && ! in_array( 'woocommerce/woocommerce.php', $active_plugins, true ) ) {
|
||
|
|
deactivate_plugins( plugin_basename( WC_EDM_PLUGIN_FILE ) );
|
||
|
|
wp_die(
|
||
|
|
esc_html__( 'WooCommerce Email Discount Manager requires WooCommerce to be installed and active. Please activate WooCommerce first.', 'wc-email-discount' ),
|
||
|
|
esc_html__( 'Plugin activation error', 'wc-email-discount' ),
|
||
|
|
array( 'back_link' => true )
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
require_once WC_EDM_PLUGIN_DIR . 'includes/class-db.php';
|
||
|
|
WC_EDM_DB::create_tables();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Plugin deactivation: clear scheduled jobs. Data is left untouched.
|
||
|
|
*/
|
||
|
|
public static function deactivate() {
|
||
|
|
require_once WC_EDM_PLUGIN_DIR . 'includes/class-audit-log.php';
|
||
|
|
WC_EDM_Audit_Log::unschedule_prune();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
register_activation_hook( __FILE__, array( 'WC_Email_Discount_Manager', 'activate' ) );
|
||
|
|
register_deactivation_hook( __FILE__, array( 'WC_Email_Discount_Manager', 'deactivate' ) );
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Access the main plugin instance.
|
||
|
|
*
|
||
|
|
* @return WC_Email_Discount_Manager
|
||
|
|
*/
|
||
|
|
function wc_edm() {
|
||
|
|
return WC_Email_Discount_Manager::instance();
|
||
|
|
}
|
||
|
|
|
||
|
|
wc_edm();
|