*/ private $modules = array(); /** * Whether boot() already ran. * * @since 1.0.0 * * @var bool */ private $booted = false; /** * Constructor. * * @since 1.0.0 * * @param Settings $settings Settings store. */ public function __construct( Settings $settings ) { $this->settings = $settings; } /** * Registers a module. Must happen before boot(). * * @since 1.0.0 * * @param Module $module Module instance. * @param bool $core Whether the module is always on. * @return void */ public function register( Module $module, bool $core = false ): void { $id = $module->id(); if ( $this->booted || isset( $this->modules[ $id ] ) || 1 !== preg_match( '/^[a-z0-9_]+$/', $id ) ) { _doing_it_wrong( __METHOD__, sprintf( 'Module "%s" is invalid, a duplicate, or registered after boot.', esc_html( $id ) ), esc_html( ELEVENRANK_VERSION ) ); return; } $this->modules[ $id ] = array( 'module' => $module, 'core' => $core, ); } /** * Whether a registered module is active. * * @since 1.0.0 * * @param string $id Module id. * @return bool */ public function is_active( string $id ): bool { if ( ! isset( $this->modules[ $id ] ) ) { return false; } if ( $this->modules[ $id ]['core'] ) { return true; } $states = $this->settings->get( 'modules' ); return ! isset( $states[ $id ] ) || (bool) $states[ $id ]; } /** * Every registered module with its name and state, for the admin screens. * * Only call this after the `init` action: module names are translated. * * @since 1.0.0 * * @return array */ public function describe(): array { $modules = array(); foreach ( $this->modules as $id => $entry ) { $modules[] = array( 'id' => (string) $id, 'label' => $entry['module']->label(), 'core' => $entry['core'], 'active' => $this->is_active( (string) $id ), ); } return $modules; } /** * Boots every active module, once. * * @since 1.0.0 * * @return void */ public function boot(): void { if ( $this->booted ) { return; } $this->booted = true; foreach ( $this->modules as $id => $entry ) { if ( $this->is_active( $id ) ) { $entry['module']->boot(); } } } }