*/ private array $modules = array(); /** * Service container. * * @var Container */ private Container $container; /** * Running edition. * * @var Edition */ private Edition $running_edition; /** * Constructor. * * @param Container $container Service container. * @param Edition $running_edition Running edition. */ private function __construct( Container $container, Edition $running_edition ) { $this->container = $container; $this->running_edition = $running_edition; } /** * Choose the edition. Only effective before boot. * * @param Edition $edition Edition to run. */ public static function use_edition( Edition $edition ): void { if ( null === self::$instance ) { self::$edition = $edition; } } /** * The edition that is (or will be) running. */ public static function edition(): Edition { self::$edition ??= new LiteEdition(); return self::$edition; } /** * Entry point, hooked to plugins_loaded. */ public static function boot(): void { if ( null !== self::$instance ) { return; } $requirements = new Requirements(); $problems = $requirements->check(); if ( array() !== $problems ) { $requirements->show_admin_notice( $problems ); return; } self::$instance = new self( new Container(), self::edition() ); self::$instance->start(); } /** * The booted plugin, or null when requirements failed or boot has not run. */ public static function instance(): ?self { return self::$instance; } /** * Service container. */ public function container(): Container { return $this->container; } /** * Modules that registered. * * @return list */ public function modules(): array { return $this->modules; } /** * Register kernel services, then register and boot modules. */ private function start(): void { $edition = $this->running_edition; $this->container->instance( Edition::class, $edition ); $this->container->set( Features::class, static fn(): Features => new Features( $edition, FeatureCatalog::all() ) ); $this->container->set( SettingsRegistry::class, static fn(): SettingsRegistry => new SettingsRegistry() ); $modules = array_merge( array( new CoreModule(), new ReviewsModule(), new CollectionModule(), new RequestsModule(), new FrontendModule(), new BlocksModule(), new SeoModule(), new RestModule(), new AdminModule(), new DataModule(), new CliModule() ), $edition->modules() ); /** * Filter the modules that load. * * @since 1.0.0 * @param list $modules Module instances in registration order. * @param Edition $edition Running edition. */ $modules = apply_filters( 'wpipr_modules', $modules, $edition ); $features = $this->container->get( Features::class ); foreach ( (array) $modules as $module ) { if ( ! $module instanceof Module ) { continue; } $feature = $module->feature(); if ( null !== $feature && ! $features->is_available( $feature ) ) { continue; } $module->register( $this->container ); $this->modules[] = $module; } foreach ( $this->modules as $module ) { $module->boot( $this->container ); } /** * Fires once every module has booted. * * @since 1.0.0 * @param Plugin $plugin Plugin kernel. */ do_action( 'wpipr_loaded', $this ); } }