pack-search` submenu with its built-in search module. $this->remove_search_submenu_if_exists(); if ( $this->should_add_search_submenu() ) { $page_suffix = Admin_Menu::add_menu( /** "Search" is a product name, do not translate. */ 'Jetpack Search', 'Search', 'manage_options', 'jetpack-search', array( $this, 'render' ), null, array( 'product' => 'search', 'key' => 'jetpack-search', ) ); } else { // always add the page, but hide it from the menu. $page_suffix = add_submenu_page( '', /** "Search" is a product name, do not translate. */ 'Jetpack Search', 'Search', 'manage_options', 'jetpack-search', array( $this, 'render' ) ); } if ( $page_suffix ) { add_action( 'load-' . $page_suffix, array( $this, 'admin_init' ) ); } } /** * Render the dashboard page. * * The generated render function is missing where the package was never built. */ public function render() { $render_function = $this->wp_build_render_function(); if ( function_exists( $render_function ) ) { call_user_func( $render_function ); } } /** * Test whether we should show Search menu. * * @return boolean Show search sub menu or not. */ protected function should_add_search_submenu() { /** * The filter allows to ommit adding a submenu item for Jetpack Search. * * @since 0.11.2 * * @param boolean $should_add_search_submenu Default value is true. */ return apply_filters( 'jetpack_search_should_add_search_submenu', current_user_can( 'manage_options' ) ); } /** * Remove `jetpack-search` submenu page */ protected function remove_search_submenu_if_exists() { remove_submenu_page( 'jetpack', 'jetpack-search' ); } /** * Initialize the admin resources. */ public function admin_init() { add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_scripts' ) ); } /** * Enqueue admin scripts. */ public function load_admin_scripts() { if ( $this->should_enqueue_tracking_script() ) { // Required for Analytics. Tracking::register_tracks_functions_scripts( true ); } // wp-build enqueues the app itself; this empty handle exists only to // print the initial state before boot runs on DOMContentLoaded. wp_register_script( self::DATA_SCRIPT_HANDLE, false, array(), Package::VERSION, true ); wp_enqueue_script( self::DATA_SCRIPT_HANDLE ); // The i18n loader is registered on every admin page but only enqueued // when depended on; the esbuild bundle doesn't pull it in. if ( wp_script_is( 'wp-jp-i18n-loader', 'registered' ) ) { wp_enqueue_script( 'wp-jp-i18n-loader' ); } // Add objects to be passed to the initial state of the app. // Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280. wp_add_inline_script( self::DATA_SCRIPT_HANDLE, ( new Initial_State() )->render(), 'before' ); // Connection initial state. Connection_Initial_State::render_script( self::DATA_SCRIPT_HANDLE ); } /** * Check if we should enqueue the tracking script. */ protected function should_enqueue_tracking_script() { return ! ( new Status() )->is_offline_mode() && $this->connection_manager->is_connected(); } /** * Deactivate search module if plan doesn't support search. * * @param \WP_Screen $current_screen Creent screen object. */ public function check_plan_deactivate_search_module( $current_screen ) { // Only run on Jetpack admin pages. // The first two checks for current screen are cheap to run on every page. if ( property_exists( $current_screen, 'base' ) && strpos( $current_screen->base, 'jetpack_page_' ) !== false && ( ! $this->plan->supports_search() || $this->plan->must_upgrade() ) ) { $this->module_control->deactivate(); } } }