init(); } /** * Initialize plugin */ private function init() { // Load plugin files $this->load_files(); // Initialize hooks $this->init_hooks(); } /** * Load required files */ private function load_files() { // Load admin functionality if (is_admin()) { require_once AIREFS_TRACKING_PLUGIN_DIR . 'includes/admin.php'; } require_once AIREFS_TRACKING_PLUGIN_DIR . 'includes/request-policy.php'; require_once AIREFS_TRACKING_PLUGIN_DIR . 'includes/queue.php'; // Load tracking functionality require_once AIREFS_TRACKING_PLUGIN_DIR . 'includes/tracking.php'; } /** * Initialize WordPress hooks */ private function init_hooks() { // Plugin activation/deactivation hooks register_activation_hook(AIREFS_TRACKING_PLUGIN_FILE, array($this, 'activate')); register_deactivation_hook(AIREFS_TRACKING_PLUGIN_FILE, array($this, 'deactivate')); // Init hook add_action('init', array($this, 'init_plugin')); // Enqueue scripts and styles add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); // Add settings link on plugins page add_filter('plugin_action_links_' . AIREFS_TRACKING_PLUGIN_BASENAME, array($this, 'add_settings_link')); } /** * Plugin activation */ public function activate($network_wide = false) { $default_options = $this->get_default_options(); $existing_options = get_option(AIREFS_TRACKING_OPTIONS_NAME, false); if (false === $existing_options) { add_option(AIREFS_TRACKING_OPTIONS_NAME, $default_options); } elseif (is_array($existing_options)) { update_option( AIREFS_TRACKING_OPTIONS_NAME, array_merge($default_options, $existing_options, array('plugin_version' => AIREFS_TRACKING_VERSION)) ); } else { update_option(AIREFS_TRACKING_OPTIONS_NAME, $default_options); } // Enable WP Rocket integration if WP Rocket is active if (class_exists('AirefsTrackingCore')) { AirefsTrackingCore::enable_wp_rocket_integration(); } AirefsTrackingQueue::resume($network_wide); $this->maybe_migrate_plugin(); } /** * Plugin deactivation */ public function deactivate($network_wide = false) { // Disable WP Rocket integration if WP Rocket is active if (class_exists('AirefsTrackingCore')) { AirefsTrackingCore::disable_wp_rocket_integration(); } AirefsTrackingQueue::pause($network_wide); $this->remove_htaccess_rules(); } /** * Initialize plugin functionality */ public function init_plugin() { $this->maybe_migrate_plugin(); } /** * Get default plugin options. * * @return array Default options. */ private function get_default_options() { return array( 'access_token' => '', 'tracking_enabled' => true, 'api_endpoint' => 'https://api.getairefs.com', 'enable_cache_vary' => false, 'plugin_version' => AIREFS_TRACKING_VERSION, ); } /** * Run lightweight update migrations for active installs. */ private function maybe_migrate_plugin() { $options = get_option(AIREFS_TRACKING_OPTIONS_NAME, array()); if (!is_array($options)) { $options = array(); } $updated = array_merge($this->get_default_options(), $options); $updated['plugin_version'] = AIREFS_TRACKING_VERSION; if (empty($options['htaccess_cleanup_complete'])) { $updated['htaccess_cleanup_complete'] = $this->remove_htaccess_rules(); if ($updated['htaccess_cleanup_complete'] && isset($options['htaccess_cleanup_complete'])) { set_transient('airefs_cleanup_completed', true, 300); } } if ($updated !== $options) { update_option(AIREFS_TRACKING_OPTIONS_NAME, $updated); } } /** * Remove htaccess rules for AI bot exclusion */ private function remove_htaccess_rules() { // Get the htaccess file path $htaccess_file = ABSPATH . '.htaccess'; // Nothing to remove when the site has no htaccess file. if (!file_exists($htaccess_file)) { return true; } return $this->remove_with_markers($htaccess_file, AIREFS_TRACKING_HTACCESS_MARKER); } /** * Remove a marker block from a file, including the marker comments. * * @param string $filename File path. * @param string $marker Marker name. * @return bool True when no block exists or the block was removed. */ private function remove_with_markers($filename, $marker) { $contents = file_get_contents($filename); if (!is_string($contents)) { return false; } if (!preg_match('/^\s*' . preg_quote('# BEGIN ' . $marker, '/') . '\s*$/m', $contents)) { return true; } if (!is_writable($filename)) { return false; } $fp = fopen($filename, 'r+'); if (!$fp) { return false; } if (!flock($fp, LOCK_EX)) { fclose($fp); return false; } $contents = stream_get_contents($fp); $start_marker = '# BEGIN ' . $marker; $end_marker = '# END ' . $marker; $eol = preg_match('/\r\n|\n|\r/', $contents, $matches) ? $matches[0] : "\n"; $lines = preg_split('/\r\n|\n|\r/', $contents); $new_lines = array(); $inside_marker = false; $removed_marker = false; foreach ($lines as $line) { if (!$inside_marker && trim($line) === $start_marker) { $inside_marker = true; $removed_marker = true; continue; } if ($inside_marker) { if (trim($line) === $end_marker) { $inside_marker = false; } continue; } $new_lines[] = $line; } if (!$removed_marker || $inside_marker) { flock($fp, LOCK_UN); fclose($fp); return !$inside_marker; } $new_contents = implode($eol, $new_lines); fseek($fp, 0); $bytes = fwrite($fp, $new_contents); $success = $bytes === strlen($new_contents); if ($success) { $success = ftruncate($fp, ftell($fp)); } fflush($fp); flock($fp, LOCK_UN); fclose($fp); return $success; } /** * Enqueue admin scripts and styles * * @param string $hook Current admin page hook */ public function admin_enqueue_scripts($hook) { // Only load on plugin settings page if ('settings_page_airefs-tracking' !== $hook) { return; } wp_enqueue_style( 'airefs-tracking-admin', AIREFS_TRACKING_PLUGIN_URL . 'assets/css/admin.css', array(), AIREFS_TRACKING_VERSION ); wp_enqueue_script( 'airefs-tracking-admin-js', AIREFS_TRACKING_PLUGIN_URL . 'assets/js/admin.js', array('jquery'), // It depends on jQuery AIREFS_TRACKING_VERSION, true // Load in the footer ); // Pass data to the admin script wp_localize_script( 'airefs-tracking-admin-js', 'airefsAdmin', // This will be the JS object name array( 'nonce' => wp_create_nonce('airefs_test_connection'), 'ajaxUrl' => admin_url('admin-ajax.php'), 'strings' => array( 'hide' => __('Hide', 'airefs-ai-search-analytics-tracking'), 'show' => __('Show', 'airefs-ai-search-analytics-tracking'), 'testing' => __('Testing...', 'airefs-ai-search-analytics-tracking'), 'testConnection' => __('Test Connection', 'airefs-ai-search-analytics-tracking'), 'testFailed' => __('Connection test failed. Please try again.', 'airefs-ai-search-analytics-tracking'), ) ) ); } /** * Add settings link to plugins page * * @param array $links Plugin action links * @return array Modified plugin action links */ public function add_settings_link($links) { $settings_link = '' . __('Settings', 'airefs-ai-search-analytics-tracking') . ''; array_unshift($links, $settings_link); return $links; } } /** * Initialize the plugin */ function airefs_tracking_init() { return AirefsTracking::get_instance(); } // Initialize plugin airefs_tracking_init();