' . __('Settings', 'akz-checkout-fields-manager-for-woocommerce') . '',
'' . __('Docs', 'akz-checkout-fields-manager-for-woocommerce') . '',
/**'' . __('Get Pro', 'akz-checkout-fields-manager-for-woocommerce') . '',*/
);
return array_merge($plugin_links, $links);
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'cfep_plugin_action_links');
// Declare WooCommerce HPOS compatibility
add_action('before_woocommerce_init', function() {
if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('cart_checkout_blocks', __FILE__, true);
}
});
// Define plugin constants
define('CFEP_VERSION', '1.0.0');
define('CFEP_PLUGIN_FILE', __FILE__);
define('CFEP_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('CFEP_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CFEP_PLUGIN_BASENAME', plugin_basename(__FILE__));
// In the includes() method:
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-checkout-detector.php';
// Load deactivation feedback
require_once CFEP_PLUGIN_DIR . 'includes/admin/class-cfep-deactivation-feedback.php';
/**
* Main Checkout Field Editor FREE Class
*/
final class CFEP_Plugin {
/**
* The single instance of the class
*/
private static $instance = null;
/**
* Main Instance
*/
public static function instance() {
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->init_hooks();
// init_block_integration removed (duplicate integration registration)
}
/**
* Initialize Block Integration early
*/
private function init_block_integration() {
add_action('woocommerce_blocks_loaded', function() {
// Try to autoload the class
if (!interface_exists('Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface')) {
// Try require it directly
$interface_file = WP_PLUGIN_DIR . '/woocommerce/packages/woocommerce-blocks/src/Integrations/IntegrationInterface.php';
if (file_exists($interface_file)) {
require_once $interface_file;
} else {
return;
}
}
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-integration.php';
add_action('woocommerce_blocks_checkout_block_registration', function($integration_registry) {
$integration_registry->register(new CFEP_Block_Integration());
}, 10);
}, 999); // Late priority
}
/**
* Hook into actions and filters
*/
private function init_hooks() {
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
add_action('plugins_loaded', array($this, 'init'), 0);
}
/**
* Initialize the plugin
*/
public function init() {
// Check if WooCommerce is active
if (!$this->is_woocommerce_active()) {
add_action('admin_notices', array($this, 'woocommerce_missing_notice'));
return;
}
$this->includes();
$this->init_classes();
}
/**
* Include required core files
*/
public function includes() {
// Core classes
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-install.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-field-types.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-field-renderer.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-wc-fields-loader.php'; // NEW: WooCommerce fields loader
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-field-manager.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-cfep-security.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-validator.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-templates.php';
// Admin classes
if (is_admin()) {
require_once CFEP_PLUGIN_DIR . 'includes/admin/class-cfep-admin.php';
require_once CFEP_PLUGIN_DIR . 'includes/admin/class-cfep-admin-menu.php';
require_once CFEP_PLUGIN_DIR . 'includes/admin/class-cfep-admin-assets.php';
}
// Frontend classes
if (!is_admin()) {
require_once CFEP_PLUGIN_DIR . 'includes/frontend/class-cfep-frontend.php';
}
// CRITICAL: Load checkout class always (needed for admin order display)
require_once CFEP_PLUGIN_DIR . 'includes/frontend/class-cfep-checkout.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-wc-fields-loader.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-default-fields-visibility.php';
// Include email display handler
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-email-display.php';
// REST API
require_once CFEP_PLUGIN_DIR . 'includes/api/class-cfep-rest-api.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-field-manager.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-field-ordering.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-handler.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-additional-checkout-fields.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-checkout-locale-injection.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-field-validation.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-field-validation.php';
require_once CFEP_PLUGIN_DIR . 'includes/admin/class-cfep-review-notice.php';
require_once CFEP_PLUGIN_DIR . 'includes/blocks/class-cfep-additional-fields-api.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-checkout-integration.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-address-fields-override.php';
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-checkout-field-ordering.php';
// Include Block Checkout Reorder class
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-block-checkout-reorder.php';
// Frontend classes
if (!is_admin()) {
require_once CFEP_PLUGIN_DIR . 'includes/frontend/class-cfep-checkout-scripts.php';
require_once CFEP_PLUGIN_DIR . 'includes/frontend/class-cfep-block-simple-frontend.php';
}
}
/**
* Initialize classes
*/
public function init_classes() {
// Initialize WC fields loader
CFEP_WC_Fields_Loader::instance();
// Initialize frontend
if (!is_admin()) {
CFEP_Block_Field_Manager::instance();
// CRITICAL FIX: Only load Block frontend on Block Checkout pages
// Use a late hook to check checkout type
add_action('wp', array($this, 'maybe_init_block_frontend'), 1);
}
// Initialize field manager
CFEP_Field_Manager::instance();
if (is_admin()) {
CFEP_Review_Notice::instance();
CFEP_Deactivation_Feedback::instance();
}
// Initialize admin
if (is_admin()) {
CFEP_Admin::instance();
CFEP_Admin_Menu::instance();
CFEP_Admin_Assets::instance();
}
// Initialize frontend
if (!is_admin()) {
CFEP_Frontend::instance();
CFEP_Checkout_Scripts::instance(); // Initialize scripts here!
}
// CRITICAL: Load Checkout class always (needed for admin order display hook)
CFEP_Checkout::instance();
// DISABLED: Old reorder script conflicts with new email-first reordering
// CFEP_Block_Checkout_Reorder::instance();
// Initialize REST API
CFEP_REST_API::instance();
CFEP_Field_Validation::instance();
CFEP_Block_Field_Validation::instance();
CFEP_Block_Default_Fields_Visibility::instance();
CFEP_Block_Checkout_Integration::instance();
CFEP_Block_Checkout_Locale_Injection::instance();
CFEP_Address_Fields_Override::instance();
CFEP_Block_Checkout_Field_Ordering::instance();
CFEP_Block_WC_Fields_Loader::instance();
CFEP_Block_Handler::instance();
// Schema-driven: auto-register CFEP fields in Block Checkout (WC 8.9+).
// CFEP_Additional_Checkout_Fields::instance(); // DISABLED for Block Integration Pro
CFEP_Additional_Fields_API::instance();
}
/**
* Maybe initialize Block frontend (only on Block Checkout)
*/
public function maybe_init_block_frontend() {
// Only on checkout page
if (!is_checkout() || is_order_received_page()) {
return;
}
// Check if using Block Checkout
if (!function_exists('wc_get_page_id')) {
return;
}
$checkout_page_id = wc_get_page_id('checkout');
if (!$checkout_page_id) {
return;
}
$post = get_post($checkout_page_id);
if (!$post) {
return;
}
// If has Classic shortcode, DON'T load Block frontend
if (strpos($post->post_content, '[woocommerce_checkout]') !== false) {
return;
}
// If has Block Checkout, load Block frontend
if (function_exists('has_block') && has_block('woocommerce/checkout', $post)) {
CFEP_Block_Simple_Frontend::instance();
return;
}
// Default: assume Classic (don't load Block frontend)
}
/**
* Check if WooCommerce is active
*/
private function is_woocommerce_active() {
return class_exists('WooCommerce');
}
/**
* WooCommerce missing notice
*/
public function woocommerce_missing_notice() {
?>
WooCommerce'
),
array( 'a' => array( 'href' => array() ) )
);
?>
is_woocommerce_active()) {
deactivate_plugins(CFEP_PLUGIN_BASENAME);
wp_die(
esc_html__('Checkout Field Editor FREE requires WooCommerce to be installed and active.', 'akz-checkout-fields-manager-for-woocommerce'),
'Plugin Activation Error',
array('back_link' => true)
);
}
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-install.php';
CFEP_Install::activate();
}
/**
* Plugin deactivation
*/
public function deactivate() {
require_once CFEP_PLUGIN_DIR . 'includes/class-cfep-install.php';
CFEP_Install::deactivate();
}
}
/**
* Returns the main instance of CFEP_Plugin
*/
function CFEP() {
return CFEP_Plugin::instance();
}
// Initialize the plugin
CFEP();
// Language (XML) selector handler
add_action('admin_post_cfep_set_language', function() {
if (!current_user_can('manage_woocommerce')) {
wp_die('Unauthorized');
}
if (!isset($_POST['cfep_lang_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['cfep_lang_nonce'])), 'cfep_set_language')) {
wp_die('Invalid nonce');
}
$code = isset($_POST['code']) ? sanitize_text_field(wp_unslash($_POST['code'])) : 'en';
update_option('cfep_language', $code);
wp_safe_redirect(wp_get_referer() ?: admin_url('admin.php?page=checkout-field-editor'));
exit;
});
/**
* ============================================
* AUTO CACHE CLEARING SYSTEM
* ============================================
* Clears all caches when checkout fields are modified
*/
// Function to clear all caches
function cfep_clear_all_caches() {
// Clear WordPress object cache
wp_cache_flush();
// Clear all plugin transients
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_cfep_%' OR option_name LIKE '_transient_timeout_cfep_%'");
// Clear WooCommerce cache
if (function_exists('wc_delete_shop_order_transients')) {
wc_delete_shop_order_transients();
}
// Clear WooCommerce sessions
if (class_exists('WC_Cache_Helper')) {
WC_Cache_Helper::invalidate_cache_group('checkout');
}
// W3 Total Cache
if (function_exists('w3tc_flush_all')) {
w3tc_flush_all();
}
// WP Super Cache
if (function_exists('wp_cache_clear_cache')) {
wp_cache_clear_cache();
}
// WP Rocket
if (function_exists('rocket_clean_domain')) {
rocket_clean_domain();
}
// LiteSpeed Cache - NUCLEAR OPTION (try ALL methods)
if (class_exists('LiteSpeed_Cache_API') && method_exists('LiteSpeed_Cache_API', 'purge_all')) {
LiteSpeed_Cache_API::purge_all();
}
// LiteSpeed Cache (namespace method for v3+)
if (class_exists('LiteSpeed\Purge')) {
\LiteSpeed\Purge::purge_all();
}
// LiteSpeed Cache (direct action hook)
if (defined('LSCWP_V')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('litespeed_purge_all');
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('litespeed_purge_all_pages');
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('litespeed_purge_all_cssjs');
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('litespeed_purge_all_object');
}
// LiteSpeed Cache (function method)
if (function_exists('litespeed_purge_all')) {
litespeed_purge_all();
}
// LiteSpeed Cache (set X-LiteSpeed-Purge header)
if (!headers_sent()) {
header('X-LiteSpeed-Purge: *');
header('X-LiteSpeed-Cache-Control: no-cache');
}
// Autoptimize
if (class_exists('autoptimizeCache')) {
autoptimizeCache::clearall();
}
// WP Fastest Cache
if (function_exists('wpfc_clear_all_cache')) {
wpfc_clear_all_cache(true);
}
// SG Optimizer (SiteGround)
if (function_exists('sg_cachepress_purge_cache')) {
sg_cachepress_purge_cache();
}
// Cache Enabler
if (class_exists('Cache_Enabler')) {
Cache_Enabler::clear_complete_cache();
}
// WP Engine
if (class_exists('WpeCommon')) {
if (method_exists('WpeCommon', 'purge_memcached')) {
WpeCommon::purge_memcached();
}
if (method_exists('WpeCommon', 'clear_maxcdn_cache')) {
WpeCommon::clear_maxcdn_cache();
}
if (method_exists('WpeCommon', 'purge_varnish_cache')) {
WpeCommon::purge_varnish_cache();
}
}
// === CDN CACHE CLEARING ===
// Cloudflare (via plugin)
if (class_exists('CF\WordPress\Hooks')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('cloudflare_purge_everything');
}
// Cloudflare (via official plugin)
if (defined('CLOUDFLARE_PLUGIN_DIR') && function_exists('cloudflare_purge_cache')) {
cloudflare_purge_cache();
}
// Sucuri CDN
if (class_exists('SucuriScanCache')) {
SucuriScanCache::clearCache();
}
// StackPath (formerly MaxCDN)
if (class_exists('MaxCDN')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('stackpath_purge_all');
}
// Breeze (Cloudways)
if (class_exists('Breeze_ConfigCache')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('breeze_clear_all_cache');
}
// Swift Performance
if (class_exists('Swift_Performance_Cache')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('swift_performance_clear_all_cache');
}
// Hummingbird
if (class_exists('Hummingbird\WP_Hummingbird')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('wphb_clear_page_cache');
}
// Nitropack
if (function_exists('nitropack_sdk_purge')) {
nitropack_sdk_purge();
}
// Nginx Helper (for Nginx FastCGI cache)
if (class_exists('Nginx_Helper')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('rt_nginx_helper_purge_all');
}
// Varnish cache
if (function_exists('varnish_purge_all')) {
varnish_purge_all();
}
// Pagely
if (class_exists('PagelyCachePurge')) {
PagelyCachePurge::purgeAll();
}
// Pressable
if (class_exists('Pressable_Automated_Cache_Purge_Events')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
do_action('pressable_purge_all_caches');
}
}
// Clear cache when ANY option is updated
add_action('update_option', function($option, $old_value, $value) {
// Check if it's related to your plugin (using cfep_ prefix)
if (strpos($option, 'cfep_') !== false ||
strpos($option, 'checkout_field') !== false ||
$option === 'cfep_checkout_fields' ||
$option === 'cfep_billing_fields' ||
$option === 'cfep_shipping_fields' ||
$option === 'cfep_additional_fields') {
cfep_clear_all_caches();
}
}, 10, 3);
// Clear cache when option is added
add_action('add_option', function($option, $value) {
if (strpos($option, 'cfep_') !== false ||
strpos($option, 'checkout_field') !== false) {
cfep_clear_all_caches();
}
}, 10, 2);
// Clear cache on POST requests to admin (when forms are submitted)
add_action('admin_init', function() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST)) {
// Check if this is your plugin's page
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if (isset($_GET['page']) && (
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
strpos(sanitize_text_field(wp_unslash($_GET['page'])), 'cfep') !== false ||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
strpos(sanitize_text_field(wp_unslash($_GET['page'])), 'checkout-field') !== false
)) {
add_action('shutdown', 'cfep_clear_all_caches');
}
}
});
// Prevent checkout page caching
add_action('template_redirect', function() {
if (is_checkout() || is_cart()) {
if (!defined('DONOTCACHEPAGE')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('DONOTCACHEPAGE', true);
}
if (!defined('DONOTCACHEDB')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('DONOTCACHEDB', true);
}
if (!defined('DONOTMINIFY')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('DONOTMINIFY', true);
}
if (!defined('DONOTCDN')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('DONOTCDN', true);
}
if (!defined('DONOTCACHEOBJECT')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('DONOTCACHEOBJECT', true);
}
// LiteSpeed specific - disable cache for checkout
if (defined('LSCWP_V')) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
define('LSCACHE_NO_CACHE', true);
}
nocache_headers();
// LiteSpeed specific headers
if (!headers_sent()) {
header('X-LiteSpeed-Cache-Control: no-cache');
header('X-LiteSpeed-Tag: skip');
}
}
}, 1);
// Clear cache via AJAX (if your plugin uses it)
add_action('wp_ajax_cfep_save_field', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_update_field', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_delete_field', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_save_settings', 'cfep_clear_all_caches');
// Block checkout specific actions
add_action('wp_ajax_cfep_update_block_field_order', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_save_block_field', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_update_block_field', 'cfep_clear_all_caches');
add_action('wp_ajax_cfep_delete_block_field', 'cfep_clear_all_caches');
// NUCLEAR OPTION: Clear cache on EVERY REST API call to your endpoints
add_action('rest_after_insert_cfep_field', 'cfep_clear_all_caches', 999);
add_action('rest_delete_cfep_field', 'cfep_clear_all_caches', 999);
add_action('rest_api_init', function() {
// Hook into your plugin's REST endpoints
add_filter('rest_pre_dispatch', function($result, $server, $request) {
$route = $request->get_route();
// Clear cache for ANY request to your plugin's REST endpoints
if (strpos($route, '/cfep/') !== false) {
// Schedule cache clear AFTER the request completes
add_action('shutdown', 'cfep_clear_all_caches', 999);
}
return $result;
}, 10, 3);
});
// Clear cache when database tables are modified
add_action('wpdb_query', function($query) {
global $wpdb;
$table_name = $wpdb->prefix . 'cfep_block_fields';
// Check if query modifies your plugin's tables
if (strpos($query, $table_name) !== false) {
if (preg_match('/^(INSERT|UPDATE|DELETE|REPLACE)/i', trim($query))) {
// Schedule cache clear
add_action('shutdown', 'cfep_clear_all_caches', 999);
}
}
});
// Clear cache when ANY post/page is saved (in case it contains checkout shortcode)
add_action('save_post', function($post_id) {
// Check if it's checkout page or contains woocommerce shortcode
$post = get_post($post_id);
if ($post && (
strpos($post->post_content, '[woocommerce_checkout]') !== false ||
strpos($post->post_content, 'wp:woocommerce/checkout') !== false ||
$post->post_name === 'checkout'
)) {
cfep_clear_all_caches();
}
}, 999);
// Clear cache when plugin is activated/deactivated
register_activation_hook(__FILE__, 'cfep_clear_all_caches');
register_deactivation_hook(__FILE__, 'cfep_clear_all_caches');
/**
* ============================================
* END AUTO CACHE CLEARING SYSTEM
* ============================================
*/
/**
* ============================================
* DEFAULT "USE SAME ADDRESS FOR BILLING"
* ============================================
*/
// For Block Checkout - make "Use same address" checked by default
add_filter('woocommerce_ship_to_different_address_checked', '__return_false');
// For Classic Checkout
add_filter('woocommerce_checkout_get_value', function($value, $input) {
if ($input === 'ship_to_different_address') {
return false;
}
return $value;
}, 10, 2);