Administration: Allow floats for menu positions.

Permit plugin authors to pass the menu position as a float in `add_menu_page()` and `add_submenu_page()`. This allows for a common practice within major plugins to avoid menu collisions by passing a float.

Follow up to [52569].

Props justinbusa, dd32, welcher, SergeyBiryukov, kirtan95, audrasjb, Cybr, chaion07, costdev, peterwilsoncc.
See #40927.


Built from https://develop.svn.wordpress.org/trunk@53104


git-svn-id: http://core.svn.wordpress.org/trunk@52693 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Peter Wilson 2022-04-08 06:17:05 +00:00
parent 35913a6309
commit 5e885b798f
2 changed files with 71 additions and 76 deletions

View File

@ -1284,20 +1284,20 @@ function uninstall_plugin( $plugin ) {
* @global array $_registered_pages * @global array $_registered_pages
* @global array $_parent_pages * @global array $_parent_pages
* *
* @param string $page_title The text to be displayed in the title tags of the page when the menu is selected. * @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 $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 $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 page and only * @param string $menu_slug The slug name to refer to this menu by. Should be unique for this menu page and only
* include lowercase alphanumeric, dashes, and underscores characters to be compatible * include lowercase alphanumeric, dashes, and underscores characters to be compatible
* with sanitize_key(). * with sanitize_key().
* @param callable $function Optional. The function to be called to output the content for this page. * @param callable $function Optional. The function to be called to output the content for this page.
* @param string $icon_url Optional. The URL to the icon to be used for this menu. * @param string $icon_url Optional. The URL to the icon to be used for this menu.
* * Pass a base64-encoded SVG using a data URI, which will be colored to match * * Pass a base64-encoded SVG using a data URI, which will be colored to match
* the color scheme. This should begin with 'data:image/svg+xml;base64,'. * the color scheme. This should begin with 'data:image/svg+xml;base64,'.
* * Pass the name of a Dashicons helper class to use a font icon, * * Pass the name of a Dashicons helper class to use a font icon,
* e.g. 'dashicons-chart-pie'. * e.g. 'dashicons-chart-pie'.
* * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
* @param int $position Optional. The position in the menu order this item should appear. * @param int|float $position Optional. The position in the menu order this item should appear.
* @return string The resulting page's hook_suffix. * @return string The resulting page's hook_suffix.
*/ */
function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) { function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function = '', $icon_url = '', $position = null ) {
@ -1323,27 +1323,22 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $func
$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url ); $new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
if ( null === $position ) { if ( null === $position || ! is_numeric( $position ) ) {
$menu[] = $new_menu; $menu[] = $new_menu;
} elseif ( isset( $menu[ "$position" ] ) ) { } elseif ( isset( $menu[ (string) $position ] ) ) {
$position = $position + substr( base_convert( md5( $menu_slug . $menu_title ), 16, 10 ), -5 ) * 0.00001; $collision_avoider = base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001;
$menu[ "$position" ] = $new_menu; $position = (string) ( $position + $collision_avoider );
$menu[ $position ] = $new_menu;
} else { } else {
if ( ! is_int( $position ) ) { /*
_doing_it_wrong( * Cast menu position to a string.
__FUNCTION__, *
sprintf( * This allows for floats to be passed as the position. PHP will normally cast a float to an
/* translators: %s: add_menu_page() */ * integer value, this ensures the float retains its mantissa (positive fractional part).
__( 'The seventh parameter passed to %s should be an integer representing menu position.' ), *
'<code>add_menu_page()</code>' * A string containing an integer value, eg "10", is treated as a numeric index.
), */
'6.0.0' $position = (string) $position;
);
// If the position is not a string (i.e. float), convert it to string.
if ( ! is_string( $position ) ) {
$position = (string) $position;
}
}
$menu[ $position ] = $new_menu; $menu[ $position ] = $new_menu;
} }
@ -1374,17 +1369,17 @@ function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $func
* @global array $_registered_pages * @global array $_registered_pages
* @global array $_parent_pages * @global array $_parent_pages
* *
* @param string $parent_slug The slug name for the parent menu (or the file name of a standard * @param string $parent_slug The slug name for the parent menu (or the file name of a standard
* WordPress admin page). * WordPress admin page).
* @param string $page_title The text to be displayed in the title tags of the page when the menu * @param string $page_title The text to be displayed in the title tags of the page when the menu
* is selected. * is selected.
* @param string $menu_title The text to be used for the menu. * @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 $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 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 * and only include lowercase alphanumeric, dashes, and underscores characters
* to be compatible with sanitize_key(). * to be compatible with sanitize_key().
* @param callable $function Optional. The function to be called to output the content for this page. * @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. * @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. * @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 ) { function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $function = '', $position = null ) {
@ -1418,43 +1413,43 @@ function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability,
} }
$new_sub_menu = array( $menu_title, $capability, $menu_slug, $page_title ); $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'
);
}
if ( null !== $position && ! is_numeric( $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'
);
$position = null;
}
if (
null === $position ||
( ! isset( $submenu[ $parent_slug ] ) || $position >= count( $submenu[ $parent_slug ] ) )
) {
$submenu[ $parent_slug ][] = $new_sub_menu; $submenu[ $parent_slug ][] = $new_sub_menu;
} else { } else {
// Append the submenu if the parent item is not present in the submenu, // Test for a negative position.
// or if position is equal or higher than the number of items in the array. $position = max( $position, 0 );
if ( ! isset( $submenu[ $parent_slug ] ) || $position >= count( $submenu[ $parent_slug ] ) ) { if ( 0 === $position ) {
$submenu[ $parent_slug ][] = $new_sub_menu; // For negative or `0` positions, prepend the submenu.
array_unshift( $submenu[ $parent_slug ], $new_sub_menu );
} else { } else {
// Test for a negative position. // Grab all of the items before the insertion point.
$position = max( $position, 0 ); $before_items = array_slice( $submenu[ $parent_slug ], 0, $position, true );
if ( 0 === $position ) { // Grab all of the items after the insertion point.
// For negative or `0` positions, prepend the submenu. $after_items = array_slice( $submenu[ $parent_slug ], $position, null, true );
array_unshift( $submenu[ $parent_slug ], $new_sub_menu ); // Add the new item.
} else { $before_items[] = $new_sub_menu;
// Grab all of the items before the insertion point. // Merge the items.
$before_items = array_slice( $submenu[ $parent_slug ], 0, $position, true ); $submenu[ $parent_slug ] = array_merge( $before_items, $after_items );
// 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. // Sort the parent array.
ksort( $submenu[ $parent_slug ] ); ksort( $submenu[ $parent_slug ] );

View File

@ -16,7 +16,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '6.0-alpha-53103'; $wp_version = '6.0-alpha-53104';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.