get_charset_collate(); require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // ── Phase 1: Leads ──────────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_leads ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, full_name varchar(191) NOT NULL, email varchar(191) NOT NULL, file_id BIGINT(20) UNSIGNED NOT NULL, ip_address VARCHAR(45) NOT NULL DEFAULT '', user_agent VARCHAR(500) NOT NULL DEFAULT '', device VARCHAR(20) NOT NULL DEFAULT '', browser VARCHAR(50) NOT NULL DEFAULT '', os VARCHAR(50) NOT NULL DEFAULT '', country VARCHAR(100) NOT NULL DEFAULT '', region VARCHAR(100) NOT NULL DEFAULT '', city VARCHAR(100) NOT NULL DEFAULT '', visit_count INT(11) UNSIGNED NOT NULL DEFAULT 1, last_seen_at DATETIME DEFAULT NULL, deal_value DECIMAL(12,2) NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY email (email), KEY file_id (file_id), KEY created_at (created_at), KEY country (country) ) $c;" ); // ── Phase 1: Tokens ─────────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_tokens ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, token VARCHAR(64) NOT NULL, lead_id BIGINT(20) UNSIGNED NOT NULL, file_id BIGINT(20) UNSIGNED NOT NULL, expires_at DATETIME NOT NULL, used TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY token (token), KEY expires_at (expires_at) ) $c;" ); // ── Phase 2: Email logs ─────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_email_logs ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, lead_id BIGINT(20) UNSIGNED NOT NULL, email varchar(191) NOT NULL, subject VARCHAR(500) NOT NULL DEFAULT '', status VARCHAR(20) NOT NULL DEFAULT 'queued', provider VARCHAR(50) NOT NULL DEFAULT 'wp_mail', error_msg TEXT, opened_at DATETIME DEFAULT NULL, click_count INT(11) UNSIGNED NOT NULL DEFAULT 0, last_clicked_at DATETIME DEFAULT NULL, sequence_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, sequence_step BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY lead_id (lead_id), KEY status (status), KEY created_at (created_at) ) $c;" ); // ── Phase 2: Integration logs ───────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_integration_logs ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, lead_id BIGINT(20) UNSIGNED NOT NULL, integration VARCHAR(50) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'skipped', response TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY lead_id (lead_id) ) $c;" ); // ── Phase 3: Forms ──────────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_forms ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, title varchar(191) NOT NULL, description TEXT, steps TINYINT(3) UNSIGNED NOT NULL DEFAULT 1, settings LONGTEXT, status VARCHAR(20) NOT NULL DEFAULT 'active', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY status (status) ) $c;" ); // ── Phase 3: Form fields ────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_form_fields ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, form_id BIGINT(20) UNSIGNED NOT NULL, field_key VARCHAR(100) NOT NULL, field_type VARCHAR(50) NOT NULL, label VARCHAR(300) NOT NULL, placeholder VARCHAR(300) NOT NULL DEFAULT '', help_text VARCHAR(500) NOT NULL DEFAULT '', options TEXT, step TINYINT(3) UNSIGNED NOT NULL DEFAULT 1, sort_order SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0, required TINYINT(1) NOT NULL DEFAULT 0, validation TEXT, conditions TEXT, settings TEXT, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY form_id (form_id), KEY sort_order (sort_order) ) $c;" ); // ── Phase 3: Submissions ────────────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_submissions ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, form_id BIGINT(20) UNSIGNED NOT NULL, lead_id BIGINT(20) UNSIGNED NOT NULL, file_id BIGINT(20) UNSIGNED NOT NULL, source_url VARCHAR(1000) NOT NULL DEFAULT '', source_post BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, referrer VARCHAR(1000) NOT NULL DEFAULT '', utm_source varchar(191) NOT NULL DEFAULT '', utm_medium varchar(191) NOT NULL DEFAULT '', utm_campaign varchar(191) NOT NULL DEFAULT '', ip_address VARCHAR(45) NOT NULL DEFAULT '', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY form_id (form_id), KEY lead_id (lead_id), KEY file_id (file_id), KEY created_at (created_at) ) $c;" ); // ── Phase 3: Submission field values ────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_submission_values ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, submission_id BIGINT(20) UNSIGNED NOT NULL, field_key VARCHAR(100) NOT NULL, field_label VARCHAR(300) NOT NULL DEFAULT '', value TEXT, PRIMARY KEY (id), KEY submission_id (submission_id), KEY field_key (field_key) ) $c;" ); // ── Phase 3: Analytics events ───────────────────────────────────── dbDelta( "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}acquis_analytics ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, event_type VARCHAR(30) NOT NULL, form_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, file_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, lead_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, source_post BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, source_url VARCHAR(1000) NOT NULL DEFAULT '', utm_source varchar(191) NOT NULL DEFAULT '', utm_medium varchar(191) NOT NULL DEFAULT '', utm_campaign varchar(191) NOT NULL DEFAULT '', ip_address VARCHAR(45) NOT NULL DEFAULT '', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY event_type (event_type), KEY file_id (file_id), KEY lead_id (lead_id), KEY created_at (created_at) ) $c;" ); // Pro tables created by AcquisitionSuite Pro plugin } /** * Returns only the options that belong to the Lite plugin. * Pro-owned options are initialised by AcquisitionSuite Pro's own activator. */ private static function get_default_options() { return array( // ── Phase 1 ─────────────────────────────────────────────────── 'acquis_link_expiry_minutes' => 30, 'acquis_allowed_types' => array( 'pdf','zip','docx','xlsx','pptx','mp4','mp3','jpg','jpeg','png' ), 'acquis_success_message' => 'Your download is ready! Click the button below.', 'acquis_success_message_standalone' => 'Thank you! Your submission has been received.', 'acquis_button_label' => 'Download File', 'acquis_modal_title' => 'Get Instant Access', 'acquis_modal_subtitle' => 'Enter your details below to download this file for free.', 'acquis_modal_header_color' => '#0D1B4B', 'acquis_modal_accent_color' => '#F97316', // ── Phase 2 ─────────────────────────────────────────────────── 'acquis_delivery_mode' => 'both', 'acquis_email_from_name' => get_bloginfo( 'name' ), 'acquis_email_from_address' => get_bloginfo( 'admin_email' ), 'acquis_email_subject' => 'Your download is ready, {full_name}!', 'acquis_email_template' => '', // seeded separately by seed_default_email_template() 'acquis_standalone_email_subject' => 'Thanks for your submission, {full_name}!', 'acquis_standalone_email_template' => '', // seeded separately by seed_default_standalone_email_template() 'acquis_email_header_color' => '#1a73e8', 'acquis_email_button_color' => '#0f9d58', 'acquis_email_button_text' => 'Download My File', 'acquis_email_footer_text' => 'You received this because you requested a file from {site_name}.', 'acquis_email_logo_url' => ACQUIS_PLUGIN_URL . 'assets/images/logo-minimal.png', // ── ESP Integrations ────────────────────────────────────────── 'acquis_mailchimp_enabled' => '0', 'acquis_mailchimp_api_key' => '', 'acquis_mailchimp_list_id' => '', 'acquis_mailchimp_tags' => '', 'acquis_mailchimp_double_optin' => '0', 'acquis_mailwizz_enabled' => '0', 'acquis_mailwizz_api_url' => '', 'acquis_mailwizz_public_key' => '', 'acquis_mailwizz_private_key' => '', 'acquis_mailwizz_list_uid' => '', 'acquis_mailwizz_double_optin' => '0', 'acquis_mailwizz_custom_fields' => array(), 'acquis_brevo_enabled' => '0', 'acquis_brevo_api_key' => '', 'acquis_brevo_list_id' => '', 'acquis_brevo_double_optin' => '0', // ── Phase 3 ─────────────────────────────────────────────────── 'acquis_analytics_period' => '30', // ── Settings ────────────────────────────────────────────────── 'acquis_show_powered_by' => '0', 'acquis_delete_data_on_uninstall' => '0', 'acquis_retention_email_logs' => 30, // Pro-owned options (whatsapp, scoring, payments, geo) are // initialised by AcquisitionSuite Pro's own activator. ); } /** * Seed the default download-email template (Lite only). * Uses add_option() so it never overwrites admin customisations. */ private static function seed_default_email_template() { if ( '' !== trim( (string) get_option( 'acquis_email_template', '' ) ) ) { return; } update_option( 'acquis_email_template', self::lite_email_template_html() ); } /** * Seed the default standalone-form email template (3.6.0) — separate * from the file-download template above since "Your file is ready" * copy makes no sense for an appointment/registration submission. * Same add_option()-style guard: never overwrites an admin's own edits. */ private static function seed_default_standalone_email_template() { if ( '' !== trim( (string) get_option( 'acquis_standalone_email_template', '' ) ) ) { return; } // Single source of truth lives on ACQUIS_Email_Template — also used // as its own runtime fallback and by the Form Builder's "Load // Default Template" button, so all three can never drift apart. update_option( 'acquis_standalone_email_template', ACQUIS_Email_Template::get_default_standalone_template() ); } /** * Minimal branded HTML email template for the Lite download notification. */ private static function lite_email_template_html() { return '
{{logo_block}}

Your file is ready!

Hi {full_name},

Thank you for your interest. Your file {file_name} is ready. Click the button below to download it now.

This link expires in {{expiry_minutes}} minutes. Do not share it.

{{footer_text}}

© {{current_year}} {site_name}. All rights reserved.

'; } private static function set_defaults() { $defaults = self::get_default_options(); foreach ( $defaults as $key => $value ) { add_option( $key, $value ); } } private static function create_protected_upload_dir() { $upload_dir = wp_upload_dir(); $protect_dir = $upload_dir['basedir'] . '/acquis-protected'; if ( ! file_exists( $protect_dir ) ) { wp_mkdir_p( $protect_dir ); } // Use WP Filesystem API for all file write operations per WP.org Guideline 7 global $wp_filesystem; if ( ! function_exists( 'WP_Filesystem' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } WP_Filesystem(); $htaccess = $protect_dir . '/.htaccess'; if ( ! file_exists( $htaccess ) ) { $wp_filesystem->put_contents( $htaccess, "Options -Indexes Deny from all ", FS_CHMOD_FILE ); } $index = $protect_dir . '/index.php'; if ( ! file_exists( $index ) ) { $wp_filesystem->put_contents( $index, '