| @@ -55,9 +55,21 @@ | ||
| 55 | 55 | if ( isset( $param['menu_title'] ) ) $this->menu_title = $param['menu_title']; |
| 56 | 56 | if ( isset( $param['menu_title_second'] ) ) $this->menu_title_second = $param['menu_title_second']; |
| 57 | 57 | if ( isset( $param['page_header'] ) ) $this->page_header = $param['page_header']; |
| 58 | 58 | if ( isset( $param['browser_header'] ) ) $this->browser_header = $param['browser_header']; |
| 59 | - if ( isset( $param['in_menu'] ) ) $this->in_menu = $param['in_menu']; | |
| 59 | + if ( isset( $param['in_menu'] ) ) $this->in_menu = $param['in_menu']; | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Filter the parent slug used to register a Booking Calendar admin page. | |
| 63 | + * | |
| 64 | + * Returning false registers the controller as a hidden WordPress plugin | |
| 65 | + * page. Its direct URL and capability check remain active, while WordPress | |
| 66 | + * does not add the page to a native submenu. | |
| 67 | + * | |
| 68 | + * @param string|false $parent_menu_slug Parent menu slug, or false for a hidden page. | |
| 69 | + * @param string $menu_slug Booking Calendar admin page slug. | |
| 70 | + */ | |
| 71 | + $this->in_menu = apply_filters( 'wpbc_admin_menu_parent_slug', $this->in_menu, $this->menu_tag ); | |
| 60 | 72 | if ( isset( $param['position'] ) ) $this->root_position = $param['position']; |
| 61 | 73 | else $this->root_position = null; |
| 62 | 74 | |
| 63 | 75 | if ( isset( $param['mune_icon_url'] ) ) $this->mune_icon_url = $param['mune_icon_url']; |
| @@ -79,8 +91,30 @@ | ||
| 79 | 91 | |
| 80 | 92 | public function load_css() { |
| 81 | 93 | do_action( 'wpbc_load_css_on_admin_page' ); |
| 82 | 94 | } |
| 95 | + | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Restore the browser title for a registered hidden plugin page. | |
| 99 | + * | |
| 100 | + * WordPress cannot always resolve a title for submenu pages registered with | |
| 101 | + * a false parent slug. The load-hook runs before admin-header.php and keeps | |
| 102 | + * PHP 8.1+ from passing null into strip_tags() while retaining the hidden | |
| 103 | + * page's normal screen hook, assets, controller, and capability check. | |
| 104 | + * | |
| 105 | + * @return void | |
| 106 | + */ | |
| 107 | + public function set_hidden_page_title() { | |
| 108 | + global $title; | |
| 109 | + | |
| 110 | + $page_title = ! empty( $this->browser_header ) ? $this->browser_header : $this->page_header; | |
| 111 | + if ( empty( $page_title ) ) { | |
| 112 | + $page_title = $this->menu_title; | |
| 113 | + } | |
| 114 | + | |
| 115 | + $title = wp_strip_all_tags( (string) $page_title ); | |
| 116 | + } | |
| 83 | 117 | |
| 84 | 118 | |
| 85 | 119 | /** |
| 86 | 120 | * Define Plugin Menu Page |
| @@ -109,8 +143,12 @@ | ||
| 109 | 143 | , $this->menu_tag // Slug |
| 110 | 144 | , array( $this, 'content' ) // Function for output content of page |
| 111 | 145 | ); |
| 112 | 146 | } |
| 147 | + | |
| 148 | + if ( false === $this->in_menu && false !== $page ) { | |
| 149 | + add_action( 'load-' . $page, array( $this, 'set_hidden_page_title' ) ); | |
| 150 | + } | |
| 113 | 151 | |
| 114 | 152 | //do_action('wpbc_define_settings_pages', $this->menu_tag ); // Define sub classes, like: page-settings-general.php $this->menu_tag - 'wpbc-settings' - its 'page' parameter in URL |
| 115 | 153 | |
| 116 | 154 | do_action('wpbc_menu_created', $this->menu_tag ); // Define sub classes, like: page-settings-general.php $this->menu_tag - 'wpbc-settings' - its 'page' parameter in URL |