[ 'label' => __( 'Documentation', 'admin-help-docs' ), 'buttons' => [ [ 'link' => add_query_arg( 'post_type', HelpDocs::$post_type, $post_new_link ), 'text' => ' ' . __( 'Add New', 'admin-help-docs' ), ], ], 'class' => Documentation::class, ], 'manage' => [ 'label' => __( 'Manage Docs', 'admin-help-docs' ), 'title' => __( 'Manage Help Docs', 'admin-help-docs' ), 'buttons' => [ [ 'link' => add_query_arg( 'post_type', HelpDocs::$post_type, $post_new_link ), 'text' => ' ' . __( 'Add New', 'admin-help-docs' ), ], ], 'link' => Bootstrap::tab_url( 'manage' ), ], 'folders' => [ 'label' => __( 'Folders', 'admin-help-docs' ), 'title' => __( 'Folders', 'admin-help-docs' ), 'link' => Bootstrap::tab_url( 'folders' ), ], 'imports' => [ 'label' => __( 'Imports', 'admin-help-docs' ), 'title' => __( 'Imported Docs', 'admin-help-docs' ), 'buttons' => [ [ 'link' => Bootstrap::tab_url( 'import' ), 'text' => ' ' . __( 'Add New', 'admin-help-docs' ), ], ], 'link' => Bootstrap::tab_url( 'imports' ), ], 'import' => [ 'label' => $import_header, 'buttons' => [ [ 'id' => 'save_import_settings', 'link' => '#', 'text' => __( 'Save Import Settings', 'admin-help-docs' ), 'form' => 'helpdocs_import_form', 'disabled' => true, ], ], 'class' => ImportEditor::class, 'hidden' => true, ], 'admin-menu' => [ 'label' => __( 'Admin Menu', 'admin-help-docs' ), 'buttons' => [ [ 'link' => '#', 'text' => __( 'Save', 'admin-help-docs' ), ], ], 'class' => AdminMenu::class, ], 'settings' => [ 'label' => __( 'Settings', 'admin-help-docs' ), 'buttons' => [ [ 'link' => '#', 'text' => __( 'Save', 'admin-help-docs' ), ], ], 'class' => Settings::class, ], 'faq' => [ 'label' => __( 'FAQ', 'admin-help-docs' ), 'title' => __( 'Frequently Asked Questions', 'admin-help-docs' ), 'buttons' => [ [ 'link' => $author_uri . 'guide/plugin/' . $text_domain, 'text' => __( 'Help Guides', 'admin-help-docs' ), 'target' => '_blank', ], [ 'link' => $author_uri . 'docs/plugin/' . $text_domain, 'text' => __( 'Developer Docs', 'admin-help-docs' ), 'target' => '_blank', ], [ 'link' => $author_uri . 'support/plugin/' . $text_domain, 'text' => __( 'Support', 'admin-help-docs' ), 'target' => '_blank', ], ], 'class' => FAQ::class, ], 'support' => [ 'label' => __( 'Contact Support', 'admin-help-docs' ), 'title' => __( 'Contact Support', 'admin-help-docs' ), 'class' => Support::class, ], ]; if ( $tab ) { return $tabs[ $tab ] ?? []; } return $tabs; } // End tabs() /** * The single instance of the class * * @var self|null */ private static ?Menu $instance = null; /** * Get the singleton instance * * @return self */ public static function instance() : self { return self::$instance ??= new self(); } // End instance() /** * Constructor */ private function __construct() { add_action( is_network_admin() ? 'network_admin_menu' : 'admin_menu', [ $this, 'register_menu' ] ); add_filter( 'parent_file', [ $this, 'submenus' ], 999 ); add_action( 'admin_body_class', [ $this, 'admin_body_class' ] ); add_filter( 'admin_title', [ $this, 'admin_title' ], 10, 2 ); add_action( 'in_admin_header', [ $this, 'admin_header' ] ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); } // End __construct() /** * Register admin menu * * @return void */ public function register_menu() : void { $title = sanitize_text_field( get_option( 'helpdocs_menu_title', Helpers::get_menu_title() ) ); $icon = Helpers::get_icon(); $position = absint( get_option( 'helpdocs_menu_position', self::$default_menu_position ) ); $parent_slug = Bootstrap::textdomain(); add_menu_page( Bootstrap::name(), $title, 'read', $parent_slug, [ $this, 'render_tab' ], $icon, $position ); if ( ! Helpers::user_can_view() ) { remove_menu_page( $parent_slug ); return; } $user_can_edit = Helpers::user_can_edit(); global $submenu; foreach ( self::tabs() as $slug => $tab ) { if ( isset( $tab[ 'hidden' ] ) && $tab[ 'hidden' ] ) { continue; } // Documentation tab is always added for users with view access, even if they don't have edit access. // Other tabs are only added if the user has edit access. if ( $slug === 'documentation' ) { $link = Bootstrap::tab_url( $slug ); $submenu[ $parent_slug ][] = [ $tab[ 'label' ] ?? '', 'read', $link ]; continue; } if ( ! $user_can_edit ) { continue; } if ( $slug === 'support' && ! get_option( 'helpdocs_contact_form' ) ) { continue; } if ( isset( $tab[ 'link' ] ) && $tab[ 'link' ] ) { $link = $tab[ 'link' ]; } else { $link = Bootstrap::tab_url( $slug ); } $submenu[ $parent_slug ][] = [ $tab[ 'label' ] ?? '', 'read', $link ]; } // Register the hidden dashboard replacement page add_submenu_page( 'index.php', __( 'Dashboard', 'admin-help-docs' ), __( 'Dashboard', 'admin-help-docs' ), 'read', 'admin-help-dashboard', [ WPDashboard::class, 'render_replacement_page' ] ); } // End register_menu() /** * Set the correct submenu file for our pages * * @param string $parent_file The current parent file slug. * @return string The modified parent file slug. */ public function submenus( $parent_file ) { global $submenu_file, $current_screen; if ( ( 'admin_page_admin-help-dashboard' ) === $current_screen->id ) { $parent_file = 'index.php'; $submenu_file = 'index.php'; return $parent_file; } $textdomain = Bootstrap::textdomain(); $options_page = 'toplevel_page_' . $textdomain; if ( is_network_admin() ) { $options_page .= '-network'; } // Help Docs Tabs if ( $current_screen->id === $options_page ) { $tab = self::get_current_tab(); if ( ! $tab ) { return $parent_file; } if ( $tab === 'import' ) { $parent_file = $textdomain; $submenu_file = Bootstrap::tab_url( 'imports' ); return $parent_file; } $submenu_file = Bootstrap::tab_url( $tab ); // Folder taxonomy } elseif ( $current_screen->id === 'edit-' . Folders::$taxonomy ) { $parent_file = $textdomain; $submenu_file = Bootstrap::tab_url( 'folders' ); // Post Type Submenus } elseif ( isset( $current_screen->post_type ) && $current_screen->post_type === HelpDocs::$post_type ) { $parent_file = $textdomain; $submenu_file = Bootstrap::tab_url( 'manage' ); } elseif ( isset( $current_screen->post_type ) && $current_screen->post_type === Imports::$post_type ) { $parent_file = $textdomain; $submenu_file = Bootstrap::tab_url( 'imports' ); } return $parent_file; } // End submenus() /** * Add custom body class on our plugin pages * * @param string $classes Existing body classes. * @return string Modified body classes. */ public function admin_body_class( $classes ) { $current_screen = get_current_screen(); $helpdocs_screen_ids = [ 'toplevel_page_' . Bootstrap::textdomain(), 'toplevel_page_' . Bootstrap::textdomain() . '-network', 'edit-' . HelpDocs::$post_type, 'edit-' . Imports::$post_type, 'edit-' . Folders::$taxonomy, ]; if ( in_array( $current_screen->id, $helpdocs_screen_ids, true ) ) { $classes .= ' helpdocs-admin-screen'; } return $classes; } // End admin_body_class() /** * Admin title filter * * @param string $title Current admin title. * @param string $page Current page slug. * * @return string */ public function admin_title( $title, $page ) { if ( $page === 'toplevel_page_' . Bootstrap::textdomain() || $page === 'toplevel_page_' . Bootstrap::textdomain() . '-network' ) { $current_tab = self::get_current_tab(); $tab = self::tabs( $current_tab ); if ( ! empty( $tab ) ) { return $tab[ 'label' ] . ' ‹ ' . Bootstrap::name(); } return Bootstrap::name(); } return $title; } // End admin_title() /** * Admin header action * * @return void */ public function admin_header() { $current_screen = get_current_screen(); if ( $current_screen->id === 'toplevel_page_' . Bootstrap::textdomain() || $current_screen->id === 'toplevel_page_' . Bootstrap::textdomain() . '-network' ) { include Bootstrap::path( 'inc/header.php' ); } } // End admin_header() public static function is_our_tab( $tab ) : bool { // Check if it's one of our pages first $is_current_page = self::get_current_page() === Bootstrap::textdomain(); if ( ! $is_current_page ) { return false; } // Then check if the tab matches $is_current_tab = self::get_current_tab() === $tab; if ( ! $is_current_tab ) { return false; } // Finally, check if the tab exists in our tabs array $tabs = self::tabs(); return isset( $tabs[ $tab ] ); } // End is_our_tab() /** * Get the current page slug * * @return string */ public static function get_current_page() : string { return isset( $_GET[ 'page' ] ) ? sanitize_text_field( wp_unslash( $_GET[ 'page' ] ) ) : ''; // phpcs:ignore } // End get_current_page() /** * Get the current tab slug * * @return string */ public static function get_current_tab() : string { return isset( $_GET[ 'tab' ] ) ? sanitize_key( wp_unslash( $_GET[ 'tab' ] ) ) : ''; // phpcs:ignore } // End get_current_tab() /** * Render tab content * * @return void */ public function render_tab() : void { $tabs = self::tabs(); $current_tab_slug = self::get_current_tab(); if ( ! $current_tab_slug || ! isset( $tabs[ $current_tab_slug ] ) || ( $current_tab_slug === 'support' && ! get_option( 'helpdocs_contact_form' ) ) ) { wp_safe_redirect( Bootstrap::tab_url( 'documentation' ) ); exit; } ?>