add_submenu_page

The timeline below displays how wordpress function add_submenu_page has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.1

/**
 * Adds a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string    $parent_slug The slug name for the parent menu (or the file name of a standard
 *                               WordPress admin page).
 * @param string    $page_title  The text to be displayed in the title tags of the page when the menu
 *                               is selected.
 * @param string    $menu_title  The text to be used for the menu.
 * @param string    $capability  The capability required for this menu to be displayed to the user.
 * @param string    $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                               and only include lowercase alphanumeric, dashes, and underscores characters
 *                               to be compatible with sanitize_key().
 * @param callable  $callback    Optional. The function to be called to output the content for this page.
 * @param int|float $position    Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug !== $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] === $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (null !== $position && !is_numeric($position)) {
        _doing_it_wrong(__FUNCTION__, sprintf(
            /* translators: %s: add_submenu_page() */
            __('The seventh parameter passed to %s should be numeric representing menu position.'),
            '<code>add_submenu_page()</code>'
        ), '5.3.0');
        $position = null;
    }
    if (null === $position || (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug]))) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            $position = absint($position);
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array.
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($callback) && !empty($hookname)) {
        add_action($hookname, $callback);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' === $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.9

/**
 * Adds a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    Optional. The function to be called to output the content for this page.
 * @param int      $position    Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug !== $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] === $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array.
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' === $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.6

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @param int      $position    The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug !== $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] === $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array.
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' === $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.5

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @param int      $position    The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array.
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' === $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.4

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @param int      $position    The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array.
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 3.1

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @param int      $position    The position in the menu order this item should appear.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if (!isset($submenu[$parent_slug]) || $position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.3

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @param int      $position    The position in the menu order this item should appear.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null)
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $new_sub_menu = array($menu_title, $capability, $menu_slug, $page_title);
    if (!is_int($position)) {
        if (null !== $position) {
            _doing_it_wrong(__FUNCTION__, sprintf(
                /* translators: %s: add_submenu_page() */
                __('The seventh parameter passed to %s should be an integer representing menu position.'),
                '<code>add_submenu_page()</code>'
            ), '5.3.0');
        }
        $submenu[$parent_slug][] = $new_sub_menu;
    } else if ($position >= count($submenu[$parent_slug])) {
        $submenu[$parent_slug][] = $new_sub_menu;
    } else {
        // Test for a negative position.
        $position = max($position, 0);
        if (0 === $position) {
            // For negative or `0` positions, prepend the submenu.
            array_unshift($submenu[$parent_slug], $new_sub_menu);
        } else {
            // Grab all of the items before the insertion point.
            $before_items = array_slice($submenu[$parent_slug], 0, $position, true);
            // Grab all of the items after the insertion point.
            $after_items = array_slice($submenu[$parent_slug], $position, null, true);
            // Add the new item.
            $before_items[] = $new_sub_menu;
            // Merge the items.
            $submenu[$parent_slug] = array_merge($before_items, $after_items);
        }
    }
    // Sort the parent array
    ksort($submenu[$parent_slug]);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.2

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management_page().
     * See wp-admin/admin.php for redirect from edit.php to tools.php.
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 5.1

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 4.9

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard
 *                              WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu
 *                              is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                              and only include lowercase alphanumeric, dashes, and underscores characters
 *                              to be compatible with sanitize_key().
 * @param callable $function    The function to be called to output the content for this page.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 4.4

/**
 * Add a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string   $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page).
 * @param string   $page_title  The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title  The text to be used for the menu.
 * @param string   $capability  The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug   The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $function    The function to be called to output the content for this page.
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 4.3

/**
 * Add a sub menu page
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @global array $submenu
 * @global array $menu
 * @global type $_wp_real_parent_file
 * @global bool $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 * @param string $menu_title The text to be used for the menu
 * @param string $capability The capability required for this menu to be displayed to the user.
 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 * @param callback $function The function to be called to output the content for this page.
 *
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv, $_registered_pages, $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 4.1

/**
 * Add a sub menu page
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 * @param string $menu_title The text to be used for the menu
 * @param string $capability The capability required for this menu to be displayed to the user.
 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 * @param callback $function The function to be called to output the content for this page.
 *
 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu;
    global $menu;
    global $_wp_real_parent_file;
    global $_wp_submenu_nopriv;
    global $_registered_pages;
    global $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 4.0

/**
 * Add a sub menu page
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 * @param string $menu_title The text to be used for the menu
 * @param string $capability The capability required for this menu to be displayed to the user.
 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 * @param callback $function The function to be called to output the content for this page.
 *
 * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu;
    global $menu;
    global $_wp_real_parent_file;
    global $_wp_submenu_nopriv;
    global $_registered_pages;
    global $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    /*
     * If the parent doesn't already have a submenu, add a link to the parent
     * as the first item in the submenu. If the submenu file is the same as the
     * parent file someone is trying to link back to the parent manually. In
     * this case, don't automatically add a link back to avoid duplication.
     */
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = array_slice($parent_menu, 0, 4);
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    /*
     * Backward-compatibility for plugins using add_management page.
     * See wp-admin/admin.php for redirect from edit.php to tools.php
     */
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level.
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}

WordPress Version: 3.7

/**
 * Add a sub menu page
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard WordPress admin page)
 * @param string $page_title The text to be displayed in the title tags of the page when the menu is selected
 * @param string $menu_title The text to be used for the menu
 * @param string $capability The capability required for this menu to be displayed to the user.
 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu)
 * @param callback $function The function to be called to output the content for this page.
 *
 * @return string|bool The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '')
{
    global $submenu;
    global $menu;
    global $_wp_real_parent_file;
    global $_wp_submenu_nopriv;
    global $_registered_pages;
    global $_parent_pages;
    $menu_slug = plugin_basename($menu_slug);
    $parent_slug = plugin_basename($parent_slug);
    if (isset($_wp_real_parent_file[$parent_slug])) {
        $parent_slug = $_wp_real_parent_file[$parent_slug];
    }
    if (!current_user_can($capability)) {
        $_wp_submenu_nopriv[$parent_slug][$menu_slug] = true;
        return false;
    }
    // If the parent doesn't already have a submenu, add a link to the parent
    // as the first item in the submenu. If the submenu file is the same as the
    // parent file someone is trying to link back to the parent manually. In
    // this case, don't automatically add a link back to avoid duplication.
    if (!isset($submenu[$parent_slug]) && $menu_slug != $parent_slug) {
        foreach ((array) $menu as $parent_menu) {
            if ($parent_menu[2] == $parent_slug && current_user_can($parent_menu[1])) {
                $submenu[$parent_slug][] = $parent_menu;
            }
        }
    }
    $submenu[$parent_slug][] = array($menu_title, $capability, $menu_slug, $page_title);
    $hookname = get_plugin_page_hookname($menu_slug, $parent_slug);
    if (!empty($function) && !empty($hookname)) {
        add_action($hookname, $function);
    }
    $_registered_pages[$hookname] = true;
    // backwards-compatibility for plugins using add_management page. See wp-admin/admin.php for redirect from edit.php to tools.php
    if ('tools.php' == $parent_slug) {
        $_registered_pages[get_plugin_page_hookname($menu_slug, 'edit.php')] = true;
    }
    // No parent as top level
    $_parent_pages[$menu_slug] = $parent_slug;
    return $hookname;
}