Commit 2362c6cf68 for wordpress.org
commit 2362c6cf6878e1833338df89cc8ed60e2810608d
Author: Mamaduka <mamaduka@git.wordpress.org>
Date: Tue Oct 27 08:31:57 2026 +0000
Administration: Map Dashicons to replacement icons from the icon library manifest.
Introduce the `WP_Icons_Registry::get_admin_icon_name_for_dashicon()` method, which returns the `core-admin` icon that replaces a given Dashicon, based on the `dashicons` property of the icon library manifest. It returns `null` if the Dashicon has no mapping or its replacement icon is not registered.
Use it in `_wp_menu_output()` in place of the hard-coded list of core menu item Dashicons. Menu items from plugins and custom post types that use a mapped Dashicon now get the SVG icon too. A Dashicon with no mapping still uses the Dashicons font.
Follow-up to [64583].
Props fushar, mamaduka, peterwilsoncc.
See #65089.
Built from https://develop.svn.wordpress.org/trunk@64798
git-svn-id: http://core.svn.wordpress.org/trunk@63948 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-admin/menu-header.php b/wp-admin/menu-header.php
index fe4cd28bfc..60671727eb 100644
--- a/wp-admin/menu-header.php
+++ b/wp-admin/menu-header.php
@@ -73,26 +73,6 @@ get_admin_page_parent();
function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) {
global $self, $parent_file, $submenu_file, $plugin_page, $typenow;
- /*
- * Dashicons back-compat: the `$menu` global keeps the Dashicons values of the core
- * menu items. Those Dashicons are only mapped to their replacement icons here, when
- * the menu is rendered.
- */
- $dashicon_replacements = array(
- 'dashicons-dashboard' => 'core-admin/dashboard',
- 'dashicons-admin-post' => 'core-admin/pin',
- 'dashicons-admin-media' => 'core-admin/media',
- 'dashicons-admin-links' => 'core-admin/link',
- 'dashicons-admin-page' => 'core-admin/page',
- 'dashicons-admin-comments' => 'core-admin/comment',
- 'dashicons-admin-appearance' => 'core-admin/brush',
- 'dashicons-admin-plugins' => 'core-admin/plugins',
- 'dashicons-admin-users' => 'core-admin/people',
- 'dashicons-admin-tools' => 'core-admin/tool',
- 'dashicons-admin-settings' => 'core-admin/settings',
- 'dashicons-admin-multisite' => 'core-admin/sites',
- );
-
$first = true;
// 0 = menu_title, 1 = capability, 2 = menu_slug, 3 = page_title, 4 = classes, 5 = hookname, 6 = icon_url.
foreach ( $menu as $key => $item ) {
@@ -145,13 +125,17 @@ function _wp_menu_output( $menu, $submenu, $submenu_as_parent = true ) {
* If the string 'none' (previously 'div') is passed instead of a URL, don't output
* the default menu image so an icon can be added to div.wp-menu-image as background
* with CSS. Dashicons and base64-encoded data:image/svg_xml URIs are also handled
- * as special cases. Dashicons that have a replacement, and namespaced icon names, are
- * rendered as inline SVG, or leave the menu image empty if the icon is not found.
- * Any other value is treated as an image URL.
+ * as special cases. Namespaced icon names are rendered as inline SVG, or leave the
+ * menu image empty if the icon is not found. Any other value is treated as an image URL.
+ *
+ * Dashicons back-compat: the `$menu` global keeps the Dashicons of the menu items,
+ * including the core ones. Dashicons with a registered replacement icon are only
+ * mapped to it here, when the menu is rendered, and other Dashicons are rendered
+ * with the Dashicons font.
*/
if ( ! empty( $item[6] ) ) {
$img = '<img src="' . esc_url( $item[6] ) . '" alt="" />';
- $icon_name = $dashicon_replacements[ $item[6] ] ?? $item[6];
+ $icon_name = WP_Icons_Registry::get_instance()->get_admin_icon_name_for_dashicon( $item[6] ) ?? $item[6];
if ( 'none' === $item[6] || 'div' === $item[6] ) {
$img = '<br />';
diff --git a/wp-includes/class-wp-icons-registry.php b/wp-includes/class-wp-icons-registry.php
index 6186a0b489..2a109fb641 100644
--- a/wp-includes/class-wp-icons-registry.php
+++ b/wp-includes/class-wp-icons-registry.php
@@ -28,6 +28,16 @@ class WP_Icons_Registry {
*/
protected static $instance = null;
+ /**
+ * Names of the icons that replace Dashicons, keyed by Dashicon class name.
+ *
+ * Built from the icon library manifest on first use.
+ *
+ * @since 7.2.0
+ * @var array<string, string>|null
+ */
+ protected $dashicon_replacements = null;
+
/**
* Constructor.
*
@@ -483,6 +493,49 @@ class WP_Icons_Registry {
return isset( $this->registered_icons[ $icon_name ] );
}
+ /**
+ * Returns the name of the icon that replaces a Dashicon in the admin interface.
+ *
+ * The replacements come from the `dashicons` property of the `core-admin`
+ * icons in the icon library manifest.
+ *
+ * @since 7.2.0
+ *
+ * @param string $dashicon Dashicon class name, such as `dashicons-admin-post`.
+ * @return string|null Namespaced name of the replacement icon, such as `core-admin/pin`,
+ * or null if the Dashicon has no replacement or the replacement
+ * is not registered.
+ */
+ public function get_admin_icon_name_for_dashicon( $dashicon ) {
+ if ( ! is_string( $dashicon ) ) {
+ return null;
+ }
+
+ if ( null === $this->dashicon_replacements ) {
+ $this->dashicon_replacements = array();
+
+ $manifest_path = ABSPATH . WPINC . '/assets/icon-library-manifest.php';
+ $manifest = is_readable( $manifest_path ) ? include $manifest_path : array();
+
+ foreach ( is_array( $manifest ) ? $manifest : array() as $icon_name => $icon_data ) {
+ if (
+ empty( $icon_data['dashicons'] ) ||
+ ! in_array( 'core-admin', $icon_data['collections'] ?? array(), true )
+ ) {
+ continue;
+ }
+
+ foreach ( $icon_data['dashicons'] as $replaced_dashicon ) {
+ $this->dashicon_replacements[ $replaced_dashicon ] = 'core-admin/' . $icon_name;
+ }
+ }
+ }
+
+ $icon_name = $this->dashicon_replacements[ $dashicon ] ?? null;
+
+ return null !== $icon_name && $this->is_registered( $icon_name ) ? $icon_name : null;
+ }
+
/**
* Utility method to retrieve the main instance of the class.
*
diff --git a/wp-includes/icons.php b/wp-includes/icons.php
index 65b7166a67..a4e6aa9ec2 100644
--- a/wp-includes/icons.php
+++ b/wp-includes/icons.php
@@ -134,7 +134,8 @@ function _wp_register_default_icons() {
* label: string,
* filePath: non-empty-string,
* collections: non-empty-list<lowercase-string&non-falsy-string>,
- * keywords?: list<string>
+ * keywords?: list<string>,
+ * dashicons?: non-empty-list<non-falsy-string>
* }> $collection
*/
$collection = include $manifest_path;
diff --git a/wp-includes/version.php b/wp-includes/version.php
index efa4692942..13d4528856 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-beta1-64797';
+$wp_version = '7.2-beta1-64798';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.