easy_svg_panel_menu_tabs
Filters which Icons panel tabs get their own entry under the Icons admin menu, and which capability a user needs to see each of those tabs.
Filter · Easy SVG · Status: Stable
easy_svg_panel_menu_tabs decides two things for the Icons panel: which tabs appear as their own entry under the Icons menu in wp-admin, and which capability a user needs to see each of them. Add your tab here and it gets a menu link that opens the panel on that tab. Give it a lower capability and, for example, editors can open the panel for your tab without seeing the rest.
Usage
apply_filters( 'easy_svg_panel_menu_tabs', array $tabs );
add_filter( 'easy_svg_panel_menu_tabs', 'myaddon_menu_tabs' );
When to use it
- Your add-on registers a panel tab with
window.EasySvgPanel.registerTab()and it should have its own link in the Icons menu. - A tab should be reachable by users without
manage_options, for example everyone who may upload files. - You want to make a free tab stricter in the interface, for example show Settings only to users with
manage_network_options.
When not to use it:
- To put a tab into the panel itself. A menu entry alone draws nothing: the tab has to be registered in JavaScript with the same id.
- To grant access to Easy SVG's own data. The free REST routes always require
manage_options, whatever you declare here. - To hide a free tab for everyone. Removing
settingsorlibraryfrom the array removes only the menu entry; the panel still draws the tab for administrators (see Pitfalls).
Parameters
Tab id as key, and as value either a plain label string or an array with the keys label and capability.
- Key: the tab id. It must be identical to the
idyou pass toregisterTab(). Use lowercase letters, digits,_and-only. - Plain string value: the label shown in the menu. The tab then requires
manage_options, which is what every tab required before capabilities per tab existed. - Array value:
label(string, falls back to the tab id when missing) andcapability(string, falls back tomanage_optionswhen missing). Any primitive capability works, including custom ones your add-on grants.
The array form needs panel contract level 2 or later (EASY_SVG_PANEL_API).
Return value
The same shape you received. The result is cast with (array), so always return the array, changed or not.
Default
array(
'settings' => __( 'Settings', 'easy-svg' ),
'library' => __( 'Icon library', 'easy-svg' ),
)
Both are plain labels, so both require manage_options. The order of the array is the order of the submenu entries, after the Icons entry itself.
Examples
A menu entry for your tab
The simplest form: a plain label, visible to administrators only.
add_filter( 'easy_svg_panel_menu_tabs', 'myaddon_menu_tabs' );
function myaddon_menu_tabs( $tabs ) {
$tabs['myaddon-report'] = __( 'SVG report', 'myaddon' );
return $tabs;
}
A tab editors may open
With the array form, the tab asks for upload_files. An editor or author now gets the Icons menu, and the panel shows them this one tab. Whatever the tab calls on the server checks the same capability.
add_filter( 'easy_svg_panel_menu_tabs', 'myaddon_menu_tabs' );
function myaddon_menu_tabs( $tabs ) {
$tabs = (array) $tabs;
$tabs['myaddon-report'] = array(
'label' => __( 'SVG report', 'myaddon' ),
'capability' => 'upload_files',
);
return $tabs;
}
add_action( 'rest_api_init', 'myaddon_routes' );
function myaddon_routes() {
register_rest_route(
'myaddon/v1',
'/report',
array(
'methods' => 'GET',
'callback' => 'myaddon_report',
'permission_callback' => function () {
return current_user_can( 'upload_files' );
},
)
);
}
Defensive: plain label on older panels
On contract level 1 the array form did not exist. Fall back to a plain label there, which means administrators only.
add_filter( 'easy_svg_panel_menu_tabs', 'myaddon_menu_tabs' );
function myaddon_menu_tabs( $tabs ) {
$tabs = (array) $tabs;
$label = __( 'SVG report', 'myaddon' );
if ( defined( 'EASY_SVG_PANEL_API' ) && 2 <= (int) EASY_SVG_PANEL_API ) {
$tabs['myaddon-report'] = array(
'label' => $label,
'capability' => 'upload_files',
);
} else {
$tabs['myaddon-report'] = $label;
}
return $tabs;
}
Place your entry first, or make Settings stricter
The array order is the menu order, so you can insert where you like. You can also raise the capability of a free tab: the menu and the panel's tab list both follow it. The free REST routes behind the tab still check manage_options, so this changes what people see, not what they could call.
add_filter( 'easy_svg_panel_menu_tabs', 'myaddon_menu_tabs', 20 );
function myaddon_menu_tabs( $tabs ) {
$tabs = (array) $tabs;
// On a multisite network: Settings only for super admins.
if ( is_multisite() && isset( $tabs['settings'] ) ) {
$tabs['settings'] = array(
'label' => __( 'Settings', 'easy-svg' ),
'capability' => 'manage_network_options',
);
}
// Our entry before all others.
return array( 'myaddon-report' => __( 'SVG report', 'myaddon' ) ) + $tabs;
}
How it works
The filter is applied in one place, the function easy_svg_panel_menu_tabs() in includes/panel.php. Several parts of the panel call that function, so your callback runs more than once per request:
easy_svg_panel_tabs_for_user()turns every entry intolabelpluscapability(a plain string becomesmanage_options) and keeps only the entries for whichcurrent_user_can()is true. It is used by the menu, by the menu highlighting and by the page render.easy_svg_panel_menu()runs onadmin_menuat priority 9, on every admin page. When the user may see no tab, it registers nothing. Otherwise it adds the top-level Icons page with the capability of the first visible tab, a self entry, and one submenu entry per visible tab with the slugeasy-svg-icons&tab=<id>.- The
submenu_filefilter marks the entry of the open tab as current. It runs thetabquery value throughsanitize_key()and only matches ids that survive that unchanged. easy_svg_panel_tab_capabilities()andeasy_svg_panel_user_caps()feedtabCaps(tab id to capability, for every entry) andcaps(capability to true or false for this user, plusmanage_options) intowindow.EasySvgPanelData.- In the browser the panel shows a tab only when
caps[ tabCaps[ id ] ]is true. A tab id that is not in your filter result is looked up asmanage_options.
Pitfalls
- A menu entry is not a tab. If no tab with that id is drawn in the panel, the link opens the panel on its first tab instead.
- Tabs from third party add-ons are drawn only while Easy SVG Pro is active and licensed. That is how
src/panel/App.jsxbuilds the tab list today. Without that licence your entry opens the first tab, and a user who holds only your custom capability gets an empty panel. Add the entry only when your tab will be drawn (the tutorial shows how). - The key must match the JavaScript id exactly. The capability lookup in the browser uses the tab id. Keep ids to lowercase letters, digits,
_and-, otherwise the menu highlighting (which usessanitize_key()) never marks your entry. - Do not reuse built-in ids:
settings,library,sets,audit,configurator,licenceandupsellbelong to Easy SVG and Easy SVG Pro. - Removing a free entry does not hide the tab. Without its entry,
settingsis simply looked up asmanage_optionsin the panel, so administrators still see it. To hide it from someone, raise its capability instead. - Lowering a free tab's capability does not help. If you give
librarythe capabilityedit_posts, editors see the tab, but every request it makes toeasy-svg/v1answers 403, because those routes checkmanage_options. - Always return the array. The value is cast with
(array): returning a string turns it into one entry with the id0. - Plain text labels only. WordPress prints submenu titles without escaping, so pass a translated string, never user input or markup.
- Use primitive capabilities.
current_user_can()is called without an object, so meta capabilities such asedit_postdo not work here. - Keep the callback cheap. It runs on every admin page while the menu is built, and again on the Icons screen. Avoid database queries and remote calls in it.
The capability you declare here controls what the menu and the panel show. It is not an access check for data. Every REST route, AJAX action or form your tab uses must call current_user_can() itself, and should verify the wp_rest nonce the panel sends. A user can always call your endpoint directly, without the panel.