options = get_option( static::OPTION_NAME, $this->get_default_options() ); if ( '' !== static::ADMIN_POST_TYPE ) { Module_Registry::register_admin_post_type( static::MODULE_ID, static::ADMIN_POST_TYPE ); } $this->init(); if ( ! $this->settings instanceof Settings_Assets_Interface ) { throw new \LogicException( static::class . ' settings must implement Settings_Assets_Interface.' ); } add_action( 'adminoptimizer_add_submenu_page', [ $this, 'add_submenu_page' ] ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_settings_assets' ] ); } /** * Return the value used when the module option has not been saved yet. * * @return mixed */ protected function get_default_options() { return []; } /** * Register the module's services and hooks after its options are loaded. */ abstract protected function init(): void; /** * Use the module settings handler as the single settings-asset entry point. * * @param string $hook_suffix Current admin page hook suffix. */ final public function enqueue_settings_assets( string $hook_suffix ): void { if ( ! $this->is_settings_screen( $hook_suffix ) ) { return; } $this->settings->enqueue_settings_assets( $hook_suffix ); } /** * Determine whether the current screen belongs to this module's settings UI. * * @param string $hook_suffix Current admin page hook suffix. */ protected function is_settings_screen( string $hook_suffix ): bool { if ( null !== $this->submenu_hook_suffix && $hook_suffix === $this->submenu_hook_suffix ) { return true; } $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; return Module_Registry::is_admin_screen_for_module( static::MODULE_ID, $screen ); } /** * Register the submenu and its canonical module ownership. * * @return string|false Hook suffix on success, false when registration fails. */ final public function add_submenu_page() { $submenu_config = $this->get_submenu_config(); if ( null === $submenu_config ) { return false; } $config = wp_parse_args( $submenu_config, [ 'page_title' => '', 'menu_title' => '', 'capability' => 'manage_options', 'menu_slug' => '', 'callback' => null, ] ); if ( '' === $config['menu_slug'] || ! is_callable( $config['callback'] ) ) { return false; } $hook_suffix = add_submenu_page( ADMINOPTIMIZER_MODULES_MENU_SLUG, $config['page_title'], $config['menu_title'], $config['capability'], $config['menu_slug'], $config['callback'] ); if ( false !== $hook_suffix ) { $this->submenu_hook_suffix = $hook_suffix; Module_Registry::register_admin_screen( static::MODULE_ID, $hook_suffix ); } return $hook_suffix; } /** * Return the module's submenu definition. * * Return null when the module does not provide a submenu. * * @return array|null */ abstract protected function get_submenu_config(): ?array; }