settings_repo = new SettingsRepository(); $api_endpoint_resolver = new ApiEndpointResolver(); $this->menu = new Menu( new MainPage() ); $this->assets = new Assets( $this->settings_repo, $api_endpoint_resolver ); $this->rest_nonce_ajax = new RestNonceAjax(); $this->activation_disclaimer_notice = new ActivationDisclaimerNotice( $this->settings_repo ); $this->privacy_policy = new PrivacyPolicy(); $this->privacy_data_hooks = new PrivacyDataHooks( new PrivacyApiClient( $this->settings_repo, $api_endpoint_resolver ) ); $this->page_styles = new PageStyles(); $attachment_ctrl = new AttachmentController( $this->settings_repo ); $settings_ctrl = new SettingsController( $this->settings_repo ); $privacy_proof_ctrl = new PrivacyProofController( $this->settings_repo ); $command_runtime = new CommandRuntime( null, null, null, null, null, null, new CommandPolicy( $this->settings_repo ) ); $this->maybe_load_dev_mode_module( $command_runtime ); $command_ctrl = new CommandController( $this->settings_repo, $command_runtime ); $this->routes = new RoutesRegistrar( $attachment_ctrl, $settings_ctrl, $privacy_proof_ctrl, $command_ctrl ); } /** * Attach plugin services to WordPress hooks. */ public function register(): void { add_action( 'admin_menu', array( $this->menu, 'register' ) ); add_action( 'admin_init', array( $this->privacy_policy, 'register' ) ); $this->privacy_data_hooks->register(); add_action( 'admin_enqueue_scripts', array( $this->assets, 'enqueue' ), 99 ); add_action( 'wp_ajax_actionpanel_ai_refresh_rest_nonce', array( $this->rest_nonce_ajax, 'handle' ) ); add_action( 'rest_api_init', array( $this->routes, 'register_routes' ) ); add_action( 'plugins_loaded', array( $this, 'migrate_settings' ), 1 ); add_action( 'admin_notices', array( $this->activation_disclaimer_notice, 'maybe_render' ) ); $this->page_styles->register(); } /** * Apply idempotent settings migrations. */ public function migrate_settings(): void { ( new SettingsMigrator( $this->settings_repo ) )->migrate(); } /** * Remove retired scheduled work when the plugin is deactivated. */ public function deactivate(): void { wp_clear_scheduled_hook( 'actionpanel_ai_disable_log_reads' ); } /** * Load the internal dev module when its files are present. * * Presence of `internal/dev-mode/` is the activation: internal builds copy * the directory in, the public WordPress.org SVN release omits it. No * wp-config constant is required, and the core plugin never hard-depends on * the module (graceful absence on public builds). */ private function maybe_load_dev_mode_module( CommandRuntime $runtime ): void { $module_path = ACTIONPANEL_AI_PLUGIN_PATH . 'internal/dev-mode/class-devmodemodule.php'; if ( ! file_exists( $module_path ) ) { return; } require_once $module_path; $module_class = 'ActionPanelAI\\Internal\\DevMode\\DevModeModule'; if ( is_callable( array( $module_class, 'load' ) ) ) { call_user_func( array( $module_class, 'load' ), $runtime ); } } }