Adds a top-level menu page.
Description
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.
Parameters
$page_title
stringrequired- The text to be displayed in the title tags of the page when the menu is selected.
$menu_title
stringrequired- The text to be used for the menu.
$capability
stringrequired- The capability required for this menu to be displayed to the user.
$menu_slug
stringrequired- 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 with sanitize_key() .
$callback
callableoptional- The function to be called to output the content for this page.
Default:
''
$icon_url
stringoptional- 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 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, e.g.
'dashicons-chart-pie'
. - Pass
'none'
to leave div.wp-menu-image empty so an icon can be added via CSS.
Default:
''
- Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme. This should begin with
$position
int|floatoptional- The position in the menu order this item should appear.
Default:
null
Source
function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) {
global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;
$menu_slug = plugin_basename( $menu_slug );
$admin_page_hooks[ $menu_slug ] = sanitize_title( $menu_title );
$hookname = get_plugin_page_hookname( $menu_slug, '' );
if ( ! empty( $callback ) && ! empty( $hookname ) && current_user_can( $capability ) ) {
add_action( $hookname, $callback );
}
if ( empty( $icon_url ) ) {
$icon_url = 'dashicons-admin-generic';
$icon_class = 'menu-icon-generic ';
} else {
$icon_url = set_url_scheme( $icon_url );
$icon_class = '';
}
$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );
if ( null !== $position && ! is_numeric( $position ) ) {
_doing_it_wrong(
__FUNCTION__,
sprintf(
/* translators: %s: add_menu_page() */
__( 'The seventh parameter passed to %s should be numeric representing menu position.' ),
'<code>add_menu_page()</code>'
),
'6.0.0'
);
$position = null;
}
if ( null === $position || ! is_numeric( $position ) ) {
$menu[] = $new_menu;
} elseif ( isset( $menu[ (string) $position ] ) ) {
$collision_avoider = base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001;
$position = (string) ( $position + $collision_avoider );
$menu[ $position ] = $new_menu;
} else {
/*
* Cast menu position to a string.
*
* This allows for floats to be passed as the position. PHP will normally cast a float to an
* integer value, this ensures the float retains its mantissa (positive fractional part).
*
* A string containing an integer value, eg "10", is treated as a numeric index.
*/
$position = (string) $position;
$menu[ $position ] = $new_menu;
}
$_registered_pages[ $hookname ] = true;
// No parent as top level.
$_parent_pages[ $menu_slug ] = false;
return $hookname;
}
Changelog
Version | Description |
---|---|
1.5.0 | Introduced. |
Examples
Add a custom menu item to the WordPress admin menu, for a user with administrator capability:
Method 1:
With this method the page-generating code should be located in
myplugin/myplugin-admin.php
:Method 2:
If you pass a base64-encoded SVG using a data URI, it will only be colored to match the color scheme IF it has a
fill
style attribute. The process is done bywp-admin/js/svg-painter.js
.$icon_url
).To add a top-level menu item which resolves to a sub-menu item, the menu slugs of each add_menu_page and add_submenu_page calls need to match. This is useful for when you need the top-level menu item label to be different to the first sub-level item. Otherwise the top-level item label is repeated as the first sub-level item.
Minimal example –
In this example; when the ‘WP Docs Orders’ top-level item is selected, it will trigger the submenu item.
Adding custom SVG icons.
I wrestled with this a bit and wanted to add in some notes when using the $icon_url parameter. From my experience and from looking on forums, using your custom icon isn’t as easy as just creating your SVG and encoding it. Here’s the step by step process to add custom SVG icon to the admin menu:
'data:image/svg+xml;base64,'
So let me expand on those steps.
Step 1
You can create your SVG graphic in any way you want as far as I can see. I created mine in Adobe Illustrator, but anything like Inkscape, Corel draw, even hardcoding it is ok.
Step 2
The painful part is cleaning up your SVG. After a lot of testing and experimenting I found that the cleaner the SVG is, the more likely it is to work. Basically, a lot of graphics programs will add in metadata and other fluff to make the SVG more widely compatible. That’s great 99% of the time, but when using it for a wordpress menu icon, it just breaks it.
This is an example of an SVG exported normally from Adobe Illustrator:
Messy, very messy. Even when we add some line breaks and indent it, there’s a lot going on.
So what we want to do is clean this up a lot and get rid of unnecessary data. You may find that the above will load if you add it as an image source but it won’t color properly with the GUI and it will probably be the wrong size. So there’s a few things we need to do:
<?xml
tag, this won’t helpdefs
element completely.fill="black"
to each path.width="20" height="20"
into the opening elementOnce that’s done, you’ll end up with an SVG file that looks more like this:
Step 3
Now you want to base64 encode your SVG. The way I did it was to pass the file into PHP’s default encoding mechanism, and copy the path into my PHP as an absolute path. You don’t want PHP to read the SVG file, base64 encode it, and pass it to the menu every time the user reloads the page, that’s just a waste of resources and time.
Step 4
Add ‘data:image/svg+xml;’ in front of the base64 SVG so it looks like this:
and that there, sir, is a perfectly valid
$icon_url
string. I would hard code that string to a variable and simply add it into your plugin every time.I hope that helps someone else, because that would have saved me several hours this morning!
Add Menu Pages with Dashicons. More dashicons check here https://developer.wordpress.org/resource/dashicons/#menu
A better example to peskyesky.
object oriented example.
TODO:
create includes/layout.php
The callback function used to display the contents of the page isn’t necessarily required to check current user’s capabilities, since the callback is not even hooked in if the user doesn’t have the right capabilities.
If you try to directly access a page for which you don’t have required capabilities, you’ll get an error page.
Quick example on how to add a menu entry with an icon.
When incorporating additional menu items using add_menu_page, the main page automatically becomes the first entry in the submenu. However, if you wish to assign a different name to the first item in the list, you can utilize the following code.