efined('WP_CLI') && WP_CLI && class_exists('WP_CLI')) { \WP_CLI::add_command('mhli smoke-test', \MHLI\CLI\SmokeTestCommand::class); \WP_CLI::add_command('mhli enrich', \MHLI\CLI\EnrichCommand::class); } // Import UI is handled by AdminMenu. Keep ImportPage class available for legacy // installs, but do not instantiate it here to avoid duplicate mhli-import menus. if (get_option('mhli_onboarding_completed')) { $this->schedule_cron_jobs(); } } private function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $tables = []; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_pricing ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, country_code char(2) NOT NULL, tier_slug varchar(30) NOT NULL, billing_period enum('monthly','yearly','onetime') NOT NULL DEFAULT 'monthly', amount_cents bigint(20) unsigned NOT NULL DEFAULT 0, currency char(3) NOT NULL, features_json longtext, is_active tinyint(1) NOT NULL DEFAULT 1, effective_from date DEFAULT NULL, effective_to date DEFAULT NULL, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_country_tier_period (country_code, tier_slug, billing_period, effective_from), KEY idx_country_active (country_code, is_active) ) $charset_collate;"; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_countries ( code char(2) NOT NULL, name_en varchar(100) NOT NULL, name_fr varchar(100) DEFAULT NULL, currency char(3) NOT NULL, currency_symbol varchar(10) NOT NULL, currency_position enum('left','right') NOT NULL DEFAULT 'left', decimal_places tinyint(1) NOT NULL DEFAULT 2, thousands_separator char(1) NOT NULL DEFAULT ',', decimal_separator char(1) NOT NULL DEFAULT '.', tax_inclusive tinyint(1) NOT NULL DEFAULT 0, stripe_country char(2) NOT NULL, supported_payment_methods json NOT NULL, tax_number_format varchar(100) DEFAULT NULL, phone_country_code varchar(5) NOT NULL, timezone_default varchar(50) NOT NULL, languages json NOT NULL, default_language char(5) NOT NULL, is_active tinyint(1) NOT NULL DEFAULT 1, is_default tinyint(1) NOT NULL DEFAULT 0, sort_order int(11) NOT NULL DEFAULT 0, PRIMARY KEY (code), KEY idx_active_default (is_active, is_default) ) $charset_collate;"; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_tiers ( slug varchar(30) NOT NULL, name_en varchar(100) NOT NULL, name_fr varchar(100) DEFAULT NULL, description_en text, description_fr text, billing_period enum('monthly','yearly','onetime') NOT NULL DEFAULT 'monthly', features_json longtext NOT NULL, is_active tinyint(1) NOT NULL DEFAULT 1, is_public tinyint(1) NOT NULL DEFAULT 1, sort_order int(11) NOT NULL DEFAULT 0, stripe_product_id varchar(100) DEFAULT NULL, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (slug) ) $charset_collate;"; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_security_events ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned DEFAULT NULL, event_type varchar(50) NOT NULL, risk_score tinyint(3) unsigned NOT NULL DEFAULT 0, ip_address varchar(45) NOT NULL, country_code char(2) DEFAULT NULL, billing_country char(2) DEFAULT NULL, phone_country char(2) DEFAULT NULL, device_fingerprint json DEFAULT NULL, metadata json DEFAULT NULL, action_taken enum('allow','challenge','block','manual_review','kyc_required') NOT NULL DEFAULT 'allow', created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_created (user_id, created_at), KEY idx_ip_created (ip_address, created_at), KEY idx_risk_created (risk_score, created_at), KEY idx_event_type (event_type) ) $charset_collate;"; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_import_jobs ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, batch_id varchar(64) NOT NULL, source varchar(30) NOT NULL, total_items int(11) NOT NULL DEFAULT 0, processed_items int(11) NOT NULL DEFAULT 0, successful_items int(11) NOT NULL DEFAULT 0, failed_items int(11) NOT NULL DEFAULT 0, status enum('pending','running','completed','failed','paused') NOT NULL DEFAULT 'pending', config_json longtext, error_log longtext, started_at datetime DEFAULT NULL, completed_at datetime DEFAULT NULL, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uq_batch_id (batch_id), KEY idx_status (status), KEY idx_source (source) ) $charset_collate;"; $tables[] = "CREATE TABLE {$wpdb->prefix}mhli_user_country ( user_id bigint(20) unsigned NOT NULL, country_code char(2) NOT NULL, locked_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, lock_method enum('billing','phone','kyc','manual') NOT NULL DEFAULT 'billing', ip_at_lock varchar(45) NOT NULL, device_fingerprint_hash char(64) NOT NULL, override_count int(11) NOT NULL DEFAULT 0, last_override_attempt datetime DEFAULT NULL, status enum('active','flagged','locked','pending_verification') NOT NULL DEFAULT 'active', PRIMARY KEY (user_id), KEY idx_country (country_code), KEY idx_status (status) ) $charset_collate;"; if (!defined('ABSPATH')) { return; } require_once ABSPATH . 'wp-admin/includes/upgrade.php'; foreach ($tables as $sql) { dbDelta($sql); } } private function schedule_cron_jobs() { if (!class_exists('ActionScheduler') || !function_exists('as_next_scheduled_action') || !function_exists('as_schedule_recurring_action')) { return; } if (!as_next_scheduled_action('mhli_daily_import')) { $timestamp = strtotime('tomorrow 6:00 AM'); as_schedule_recurring_action($timestamp, DAY_IN_SECONDS, 'mhli_daily_import'); } if (!as_next_scheduled_action('mhli_weekly_cleanup')) { $timestamp = strtotime('next sunday 3:00 AM'); as_schedule_recurring_action($timestamp, WEEK_IN_SECONDS, 'mhli_weekly_cleanup'); } } public function admin_notices() { $errors = get_option('mhli_activation_errors', []); if (!empty($errors)) { foreach ($errors as $error) { echo '
' . esc_html(\MHLI\Core\SettingsRepository::get('plugin_label', 'Listeo Importer')) . ': ' . esc_html($error) . '
MinouHub Listings Importer: ' . __('Plugin requires initial setup. Please complete the onboarding wizard.', 'mhli') . ' ' . __('Run Setup Wizard', 'mhli') . '