id === 'toplevel_page_' . self::PARENT_SLUG || str_starts_with( $screen->id, self::PARENT_SLUG . '_page_' ); } /** * The navigation items, in order, filtered for the current user. * * Read from the registered submenu rather than a hardcoded list, so an * add-on page appears here for free and a page the user cannot access never * appears at all. * * @return array * @since 1.4.0 */ public static function items(): array { global $submenu; $entries = $submenu[ self::PARENT_SLUG ] ?? []; if ( ! is_array( $entries ) ) { return []; } $items = []; foreach ( $entries as $entry ) { // WordPress submenu shape: [ 0 => menu title, 1 => capability, 2 => slug ]. if ( ! is_array( $entry ) || ! isset( $entry[0], $entry[1], $entry[2] ) ) { continue; } if ( ! current_user_can( (string) $entry[1] ) ) { continue; } $slug = (string) $entry[2]; $items[] = [ 'slug' => $slug, 'label' => wp_strip_all_tags( (string) $entry[0] ), 'url' => menu_page_url( $slug, false ), ]; } return $items; } /** * Render the page navigation above the screen content. * * Real links with `aria-current="page"`, not `role="tablist"`. Each entry is * a separate admin page load, and tab semantics promise something else * entirely — in-page panels and arrow-key navigation. Announcing tabs and * then navigating away is a worse experience for a screen-reader user than * plain links, which is exactly what these are. * * @return void * @since 1.4.0 */ public function render_navigation(): void { if ( ! self::is_albert_screen() ) { return; } $items = self::items(); // One item is not a navigation; it is a label pretending to be a choice. if ( count( $items ) < 2 ) { return; } $current = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( (string) $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen identification, no state change. ?>