|null */ private static $options = null; /** @var Aiso_Tracker */ public $tracker; /** @var Aiso_Sync */ public $sync; /** @var Aiso_Cache */ public $cache; /** @var Aiso_Settings|null */ public $settings = null; /** @var Aiso_Admin|null */ public $admin = null; /** * Get (and lazily build) the singleton. * * @return Aiso_Analytics */ public static function instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } private function __construct() { $this->maybe_upgrade(); // Always-on: collection + central sync. The cache layer must be wired before // the request is served so AI-bot requests bypass full-page caches and reach // the tracker (otherwise cache HITs exit before `init` and the hit is lost). $this->sync = new Aiso_Sync(); $this->cache = new Aiso_Cache(); $this->tracker = new Aiso_Tracker(); // Admin-only UI. if ( is_admin() ) { $this->settings = new Aiso_Settings(); $this->admin = new Aiso_Admin(); } } /** * Default option values. * * @return array */ public static function default_options() { return array( 'api_key' => '', 'sync_enabled' => 0, 'track_all_bots' => 0, 'anonymize_ip' => 1, 'retention_days' => 90, 'endpoint_base' => '', 'bypass_cache_for_ai_bots' => 1, 'remove_data_on_uninstall' => 0, ); } /** * All options, merged over defaults. * * @return array */ public static function options() { if ( null === self::$options ) { $stored = get_option( Aiso_Settings::OPTION, array() ); self::$options = wp_parse_args( is_array( $stored ) ? $stored : array(), self::default_options() ); } return self::$options; } /** * One option value. * * @param string $key Option key. * @param mixed $default Fallback. * @return mixed */ public static function option( $key, $default = null ) { $options = self::options(); return array_key_exists( $key, $options ) ? $options[ $key ] : $default; } /** * Re-run table install if the DB schema version changed. */ private function maybe_upgrade() { if ( get_option( 'aiso_db_version' ) !== Aiso_Store::DB_VERSION ) { Aiso_Store::install(); } } /** * Activation: create the table, seed defaults, schedule sync. */ public static function activate() { Aiso_Store::install(); if ( false === get_option( Aiso_Settings::OPTION ) ) { add_option( Aiso_Settings::OPTION, self::default_options() ); } if ( false === get_option( 'aiso_ip_salt' ) ) { add_option( 'aiso_ip_salt', wp_generate_password( 32, false, false ), '', false ); } Aiso_Sync::schedule(); // Push our AI-bot UAs into WP Rocket's baked cache config straight away, so // cache bypass is live without waiting for the first settings save. Aiso_Cache::refresh_cache_rules(); } /** * Deactivation: stop the cron. */ public static function deactivate() { Aiso_Sync::unschedule(); } }