' . __('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);