charset_collate = $wpdb->get_charset_collate(); $this->wpdb = $wpdb; } public static function get_instance() { if ( self::$instance === null ) { self::$instance = new self(); } return self::$instance; } public function adfuz_check_and_install_tables() { $current_version = get_option( 'adfuz_plugin_version', '0' ); if ( version_compare( ADFUZ_PLUGIN_VERSION, $current_version, '>' ) ) { if ( ! function_exists( 'dbDelta' ) ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; } $queries = array( $this->table_adfuz_ads(), $this->table_adfuz_ads_meta(), $this->table_adfuz_ad_spaces(), $this->table_adfuz_ad_spaces_meta(), $this->table_adfuz_campaigns(), $this->table_adfuz_campaign_ad_spaces(), $this->table_adfuz_campaign_ads(), $this->table_adfuz_campaigns_meta(), $this->table_adfuz_campaign_target_countries(), $this->table_adfuz_campaign_target_devices(), $this->table_adfuz_audit_logs(), $this->table_adfuz_audit_logs_meta(), ); foreach ( $queries as $query ) { try { dbDelta( $query ); } catch ( Exception $e ) { \AdFuz\Helpers\Common::log_file( array( 'Type' => 'Install DB Error', $e->getMessage(), ) ); } } update_option( 'adfuz_plugin_version', ADFUZ_PLUGIN_VERSION ); } } private function table_adfuz_ads() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_ads ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED DEFAULT NULL, ad_type VARCHAR(10) NOT NULL, title VARCHAR(100) NOT NULL, slug VARCHAR(255) NOT NULL, hide_title BOOL DEFAULT FALSE, description TEXT DEFAULT NULL, target_url VARCHAR(2083) DEFAULT NULL, media_url VARCHAR(2083) DEFAULT NULL, media_id BIGINT UNSIGNED DEFAULT NULL, script_html TEXT DEFAULT NULL, cta VARCHAR(100) DEFAULT NULL, cta_type VARCHAR(10) DEFAULT 'link', cta_position VARCHAR(10) DEFAULT 'left', link_to VARCHAR(10) DEFAULT 'link', status ENUM('active','paused','deleted', 'draft', 'pending') DEFAULT 'draft', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_ad_type (ad_type), KEY idx_status (status), UNIQUE KEY idx_slug (slug), FOREIGN KEY (user_id) REFERENCES {$this->wpdb->users}(ID) ON DELETE SET NULL ) $this->charset_collate;"; } private function table_adfuz_ads_meta() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_ads_meta ( meta_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ad_id BIGINT UNSIGNED NOT NULL, meta_key VARCHAR(255), meta_value LONGTEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (ad_id) REFERENCES {$this->wpdb->prefix}adfuz_ads(id) ON DELETE CASCADE, KEY meta_key (meta_key) ) $this->charset_collate;"; } private function table_adfuz_ad_spaces() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_ad_spaces ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED DEFAULT NULL, fallback_ad_id BIGINT UNSIGNED DEFAULT NULL, ad_format VARCHAR(20) DEFAULT NULL, ad_sequence VARCHAR(10) DEFAULT NULL, title VARCHAR(100) NOT NULL, slug VARCHAR(100) UNIQUE NOT NULL, width INT NOT NULL, height INT NOT NULL, availability INT NOT NULL DEFAULT 1, status ENUM('active', 'inactive', 'draft', 'deleted') DEFAULT 'active', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_status (status), KEY idx_slug (slug), KEY idx_ad_format (ad_format), KEY idx_ad_sequence (ad_sequence), FOREIGN KEY (user_id) REFERENCES {$this->wpdb->users}(ID) ON DELETE SET NULL, FOREIGN KEY (fallback_ad_id) REFERENCES {$this->wpdb->prefix}adfuz_ads(id) ON DELETE SET NULL ) $this->charset_collate;"; } private function table_adfuz_ad_spaces_meta() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_ad_spaces_meta ( meta_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ad_space_id BIGINT UNSIGNED NOT NULL, meta_key VARCHAR(255), meta_value LONGTEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (ad_space_id) REFERENCES {$this->wpdb->prefix}adfuz_ad_spaces(id) ON DELETE CASCADE, KEY meta_key (meta_key) ) $this->charset_collate;"; } private function table_adfuz_campaigns() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaigns ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED DEFAULT NULL, slug VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, expiry_date DATETIME DEFAULT NULL, expiry_impressions INT DEFAULT NULL, expiry_clicks INT DEFAULT NULL, targeting JSON DEFAULT NULL, start_date DATETIME DEFAULT NULL, end_date DATETIME DEFAULT NULL, pricing_model ENUM('flat', 'per_impression', 'per_click', 'mixed') DEFAULT 'flat', price DECIMAL(10,2) DEFAULT 0.00, currency VARCHAR(5) DEFAULT 'USD', fallback_ad_id BIGINT UNSIGNED DEFAULT NULL, status ENUM('pending','active','paused','expired','deleted') DEFAULT 'pending', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_status (status), UNIQUE KEY idx_slug (slug), FOREIGN KEY (user_id) REFERENCES {$this->wpdb->users}(ID) ON DELETE SET NULL, FOREIGN KEY (fallback_ad_id) REFERENCES {$this->wpdb->prefix}adfuz_ads(id) ON DELETE SET NULL ) $this->charset_collate;"; } private function table_adfuz_campaign_ad_spaces() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaign_ad_spaces ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, campaign_id BIGINT UNSIGNED NOT NULL, ad_space_id BIGINT UNSIGNED NOT NULL, display_order INT DEFAULT 0, status ENUM('active','paused') DEFAULT 'active', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (campaign_id) REFERENCES {$this->wpdb->prefix}adfuz_campaigns(id) ON DELETE CASCADE, FOREIGN KEY (ad_space_id) REFERENCES {$this->wpdb->prefix}adfuz_ad_spaces(id) ON DELETE CASCADE, UNIQUE KEY unique_campaign_adspace (campaign_id, ad_space_id) ) $this->charset_collate;"; } private function table_adfuz_campaign_ads() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaign_ads ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, campaign_id BIGINT UNSIGNED NOT NULL, ad_id BIGINT UNSIGNED NOT NULL, display_order INT DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (campaign_id) REFERENCES {$this->wpdb->prefix}adfuz_campaigns(id) ON DELETE CASCADE, FOREIGN KEY (ad_id) REFERENCES {$this->wpdb->prefix}adfuz_ads(id) ON DELETE CASCADE, UNIQUE KEY unique_campaign_ad (campaign_id,ad_id) ) $this->charset_collate;"; } private function table_adfuz_campaign_target_countries() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaign_target_countries ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, campaign_id BIGINT UNSIGNED NOT NULL, country_code CHAR(3) NOT NULL, KEY idx_country_code (country_code), FOREIGN KEY (campaign_id) REFERENCES {$this->wpdb->prefix}adfuz_campaigns(id) ON DELETE CASCADE ) $this->charset_collate;"; } private function table_adfuz_campaign_target_devices() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaign_target_devices ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, campaign_id BIGINT UNSIGNED NOT NULL, device_type ENUM('mobile', 'tablet', 'desktop', 'laptop', 'smarttv', 'all') NOT NULL, KEY idx_device_type (device_type), FOREIGN KEY (campaign_id) REFERENCES {$this->wpdb->prefix}adfuz_campaigns(id) ON DELETE CASCADE ) $this->charset_collate;"; } private function table_adfuz_campaigns_meta() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_campaigns_meta ( meta_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, campaign_id BIGINT UNSIGNED NOT NULL, meta_key VARCHAR(255), meta_value LONGTEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (campaign_id) REFERENCES {$this->wpdb->prefix}adfuz_campaigns(id) ON DELETE CASCADE, KEY meta_key (meta_key) ) $this->charset_collate;"; } private function table_adfuz_audit_logs() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_audit_logs ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user_id BIGINT UNSIGNED DEFAULT NULL, log_action VARCHAR(100) NOT NULL, entity_type VARCHAR(100) NOT NULL, entity_id BIGINT UNSIGNED NOT NULL, change_details JSON DEFAULT NULL, ip_address VARCHAR(45), user_agent VARCHAR(500) DEFAULT NULL, log_level ENUM('info', 'warning', 'error', 'critical') DEFAULT 'info', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES {$this->wpdb->users}(ID) ON DELETE SET NULL ) $this->charset_collate;"; } private function table_adfuz_audit_logs_meta() { return "CREATE TABLE IF NOT EXISTS {$this->wpdb->prefix}adfuz_audit_logs_meta ( meta_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, audit_log_id BIGINT UNSIGNED NOT NULL, meta_key VARCHAR(255), meta_value LONGTEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (audit_log_id) REFERENCES {$this->wpdb->prefix}adfuz_audit_logs(id) ON DELETE CASCADE, KEY meta_key (meta_key) ) $this->charset_collate;"; } private function get_table_method_map(): array { $map = array(); foreach ( TableName::adfuz_definitions( true ) as $def ) { $table_name = $def['table']; $method = 'table_' . str_replace( $this->wpdb->prefix, '', $table_name ); $map[ $table_name ] = $method; } return $map; } /** * (Re-)install a single table by its full table name. * Called by DatabaseToolsController::install_table(). */ public function install_single_table( string $table_name ): bool { if ( ! function_exists( 'dbDelta' ) ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; } // 1. Try free-owned tables first. $map = $this->get_table_method_map(); if ( isset( $map[ $table_name ] ) ) { $method = $map[ $table_name ]; try { dbDelta( $this->$method() ); return true; } catch ( Exception $e ) { Common::log_file( array( 'Type' => 'Install Single Table Error', 'Message' => $e->getMessage(), ) ); return false; } } /** * Filter: adfuz/install/single_table * * Allows Pro (or any add-on) to handle installation of tables * not owned by the free plugin. The free plugin knows nothing * about who handles this — it just returns the result. * * @param bool $result Default false (unhandled). * @param string $table_name Full prefixed table name. */ return (bool) apply_filters( 'adfuz/install/single_table', false, $table_name ); } public function install_all_tables(): void { if ( ! function_exists( 'dbDelta' ) ) { require_once ABSPATH . 'wp-admin/includes/upgrade.php'; } // Free tables. foreach ( $this->get_table_method_map() as $table_name => $method ) { try { dbDelta( $this->$method() ); } catch ( Exception $e ) { Common::log_file( array( 'Type' => 'Install All Tables Error', 'Message' => $e->getMessage(), ) ); } } /** * Action: adfuz/install/all_tables * * Fired after all free tables are installed. Pro hooks in here * to install its own tables. The free plugin has no knowledge * of what runs on this hook. */ do_action( 'adfuz/install/all_tables' ); } }