diff --git a/src/wp-admin/includes/menu.php b/src/wp-admin/includes/menu.php index 3cf4a5fdd6c17..96a01b5f93845 100644 --- a/src/wp-admin/includes/menu.php +++ b/src/wp-admin/includes/menu.php @@ -368,7 +368,17 @@ function sort_menu( $a, $b ) { } unset( $last_menu_key ); -if ( ! user_can_access_admin_page() ) { +if ( ! admin_page_exists() ) { + + /** + * Fires when access to an admin page which does not exist. + * + * @since 4.9.0 + */ + do_action( 'admin_page_not_found' ); + + wp_die( __( 'The requested page does not exist.' ), 403 ); +} elseif ( ! user_can_access_admin_page() ) { /** * Fires when access to an admin page is denied. diff --git a/src/wp-admin/includes/plugin.php b/src/wp-admin/includes/plugin.php index de1468352b3d9..e2f5b38fd2376 100644 --- a/src/wp-admin/includes/plugin.php +++ b/src/wp-admin/includes/plugin.php @@ -2130,6 +2130,33 @@ function get_plugin_page_hook( $plugin_page, $parent_page ) { } } +/** + * Checks if admin page exists, if the user would have the required capabilities. + * + * @since tba + * + * @global string $admin_page_parent + * @global string $plugin_page + * @global array $_registered_pages + */ +function admin_page_exists() { + global $admin_page_parent, $plugin_page, $_registered_pages; + + if ( ! isset( $admin_page_parent ) ) { + $admin_page_parent = get_admin_page_parent(); + } + + if ( isset( $plugin_page ) ) { + $hookname = get_plugin_page_hookname( $plugin_page, $admin_page_parent ); + + if ( ! isset( $_registered_pages[ $hookname ] ) ) { + return false; + } + } + + return true; +} + /** * Gets the hook name for the administrative page of a plugin. * @@ -2175,14 +2202,15 @@ function get_plugin_page_hookname( $plugin_page, $parent_page ) { * @global array $_wp_submenu_nopriv * @global string $plugin_page * @global array $_registered_pages + * @global string $admin_page_parent * * @return bool True if the current user can access the admin page, false otherwise. */ function user_can_access_admin_page() { global $pagenow, $menu, $submenu, $_wp_menu_nopriv, $_wp_submenu_nopriv, - $plugin_page, $_registered_pages; + $plugin_page, $_registered_pages, $admin_page_parent; - $parent = get_admin_page_parent(); + $parent = isset( $admin_page_parent ) ? $admin_page_parent : get_admin_page_parent(); if ( ! isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $parent ][ $pagenow ] ) ) { return false; @@ -2195,6 +2223,10 @@ function user_can_access_admin_page() { $hookname = get_plugin_page_hookname( $plugin_page, $parent ); + if ( ! admin_page_exists() ) { + return false; + } + if ( ! isset( $_registered_pages[ $hookname ] ) ) { return false; }