setup(); } return self::$instance; } /** * Setup the plugin. */ private function setup(): void { // Load the plugin classes. add_action( 'plugins_loaded', array( $this, 'load' ) ); // Register activation and deactivation hooks. register_activation_hook( WPAI_PLUGIN_FILE, array( Activation::class, 'activation_callback' ) ); register_deactivation_hook( WPAI_PLUGIN_FILE, array( Deactivation::class, 'deactivation_callback' ) ); } /** * Load the plugin classes. * * @since 0.8.0 * * @internal Used in the plugins_loaded action. */ public function load(): void { // Check plugin requirements before continuing. if ( ! ( new Requirements() )->are_requirements_met() ) { return; } // Include globals require_once WPAI_PLUGIN_DIR . 'includes/helpers.php'; // Handle any pending upgrades. ( new Upgrades() )->init(); // Handle deprecated code. ( new Deprecated() )->init(); // Add plugin action links to plugins screen. add_filter( 'plugin_action_links_' . plugin_basename( WPAI_PLUGIN_FILE ), array( $this, 'plugin_action_links' ) ); // Defer feature initialization to the 'init' action. add_action( 'init', array( $this, 'initialize_features' ), 15 ); // Register provider data globally so it is available to any plugin script. add_action( 'init', array( $this, 'register_provider_data' ), 20 ); // Register the default ability category. add_action( 'wp_abilities_api_categories_init', array( $this, 'register_ability_category' ) ); } /** * Initializes plugin features. * * @since 0.8.0 */ public function initialize_features(): void { try { // Experiments are hooked into our Loader, so we need to register them first. ( new Experiments() )->init(); // The one true registry of all features. $registry = new Registry(); // Initializes all the features. ( new Loader( $registry ) )->init(); // Initialize settings registration. ( new Settings_Registration( $registry ) )->init(); // Register admin settings page menu item and dashboard widgets. if ( is_admin() ) { Settings_Page::init( $registry ); ( new Dashboard_Widgets( $registry ) )->init(); } // Register Site Health integration. The `debug_information` and // `site_status_tests` filters are only ever consumed from admin // screens, the Site Health REST endpoints (which power the async // status checks in wp-admin/site-health.php), and the weekly // WP-Cron health-check email — never on the public front end. if ( is_admin() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { ( new Site_Health() )->init(); } } catch ( \Throwable $e ) { _doing_it_wrong( __METHOD__, sprintf( /* translators: %s: Error message. */ esc_html__( 'AI Plugin initialization failed: %s', 'ai' ), esc_html( $e->getMessage() ) ), '0.8.0' ); } } /** * Adds action links to the plugin list table. * * This adds "Settings" and "Connectors" links to * the plugin's action links on the Plugins page. * * @since 0.8.0 * * @param array $links Existing action links. * @return array Modified action links. */ public function plugin_action_links( array $links ): array { $settings_link = sprintf( '%2$s', admin_url( 'options-general.php?page=ai-wp-admin' ), esc_html__( 'Settings', 'ai' ) ); $connectors_link = sprintf( '%2$s', admin_url( 'options-connectors.php' ), esc_html__( 'Connectors', 'ai' ) ); array_unshift( $links, $connectors_link, $settings_link ); return $links; } /** * Registers provider availability data for frontend scripts. * * @since 1.0.0 */ public function register_provider_data(): void { Asset_Loader::add_global_data( 'ProviderData', get_provider_availability_data() ); } /** * Register a generic catch-all category that all Abilities we register can use. * * This can be re-evaluated in the future if we need/want more specific categories. * * @internal Used in the wp_abilities_api_categories_init action. * * @since 0.8.0 */ public function register_ability_category(): void { wp_register_ability_category( WPAI_DEFAULT_ABILITY_CATEGORY, array( 'label' => __( 'AI', 'ai' ), 'description' => __( 'Various AI features and experiments.', 'ai' ), ), ); } /** * Prevent the class from being cloned. * * @since 0.8.0 */ public function __clone() { _doing_it_wrong( __FUNCTION__, sprintf( // translators: %s: Class name. esc_html__( 'The %s class should not be cloned.', 'ai' ), esc_html( self::class ), ), '0.8.0' ); } /** * Prevent the class from being deserialized. * * @since 0.8.0 */ public function __wakeup() { _doing_it_wrong( __FUNCTION__, sprintf( // translators: %s: Class name. esc_html__( 'De-serializing instances of %s is not allowed.', 'ai' ), esc_html( self::class ), ), '0.8.0' ); } }