*/ private $problems = array(); /** * Returns the shared instance. */ public static function instance(): self { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Activation hook. Activation is always a web request, so this is a safe moment to pick the * photo folder (the outside-web-root check needs DOCUMENT_ROOT). */ public static function activate(): void { Database\Installer::activate(); Storage\Storage::location(); Admin\NoticePlace::arm(); } /** * Deactivation hook: stops the background jobs. Data stays until the plugin is deleted. */ public static function deactivate(): void { if ( function_exists( 'as_unschedule_all_actions' ) ) { Job\ActionSchedulerQueue::clear(); } } /** * Registers the plugin's hooks. Safe to call more than once. */ public function boot(): void { if ( $this->booted ) { return; } $this->booted = true; add_action( 'before_woocommerce_init', array( $this, 'declare_woocommerce_compatibility' ) ); add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ) ); } /** * Declares HPOS and Cart/Checkout blocks compatibility. * * Fitzaro never reads order data from post meta and adds nothing to checkout. */ public function declare_woocommerce_compatibility(): void { if ( ! class_exists( FeaturesUtil::class ) ) { return; } FeaturesUtil::declare_compatibility( 'custom_order_tables', FITZARO_FILE, true ); FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', FITZARO_FILE, true ); } /** * Checks requirements, then lets the modules register their hooks. */ public function on_plugins_loaded(): void { // The table does not depend on WooCommerce, and updates do not re-run the activation hook. Database\Installer::maybe_upgrade(); $this->problems = Requirements::problems( class_exists( 'WooCommerce' ), defined( 'WC_VERSION' ) ? (string) WC_VERSION : null ); if ( array() !== $this->problems ) { add_action( 'admin_notices', array( $this, 'render_requirement_notice' ) ); return; } SystemCheck::register(); Job\Jobs::register(); Api\RestController::register(); Limits\BudgetNotice::register(); Admin\SettingsTab::register(); Admin\ProviderNotice::register(); Admin\NoticePlace::register(); Admin\ProductFields::register(); Privacy\PrivacyTools::register(); Storefront\Button::register(); // Modules (REST, storefront, admin, providers) register here in later steps. } /** * Explains why the plugin is inactive, on the Plugins screen, to users who can fix it. */ public function render_requirement_notice(): void { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( ! current_user_can( 'activate_plugins' ) || null === $screen || 'plugins' !== $screen->id ) { return; } foreach ( $this->problems as $problem ) { printf( '

%s

', esc_html( $this->requirement_message( $problem ) ) ); } } /** * Human-readable text for a problem code from Requirements. * * @param string $problem Problem code. */ private function requirement_message( string $problem ): string { if ( Requirements::WOOCOMMERCE_OUTDATED === $problem ) { return sprintf( /* translators: %s: minimum WooCommerce version. */ __( 'Fitzaro needs WooCommerce %s or newer.', 'fitzaro' ), Requirements::MIN_WOOCOMMERCE ); } return __( 'Fitzaro needs WooCommerce to be installed and active.', 'fitzaro' ); } }