The WordPress coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. development team builds WordPress! Follow this site for general updates, status reports, and the occasional code debate. There’s lots of ways to contribute:
Found a bugbugA bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority.?Create a ticket in the bug tracker.
In recent years, the CI load across coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. WordPress GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ repos increased as the project evolved. This is normal for an active project.
But, the load can be especially high when running the full PHPUnit matrix at once on many PRs, such as during a release with many backportbackportA port is when code from one branch (or trunk) is merged into another branch or trunk. Some changes in WordPress point releases are the result of backporting code from trunk to the release branch. branches. Cases like this mean the number of jobs can strain the capacity of the system.
Ahead of 7.1, we’ve landed a round of trims and reliability fixes aimed at increasing capacity and running leaner while ensuring quality checks still run.
This CI work builds on the test-suite optimization work from many contributors in the past.
Two key changes
Trimmed the PHPUnit matrix to boundary PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher versions (#12719 on trunktrunkA directory in Subversion containing the latest development code in preparation for the next major release cycle. If you are running "trunk", then you are on the latest revision., #12720 for 7.0). Full PHP coverage kept, redundant database combinations dropped. Per run: ~52% fewer jobs and ~54% fewer job-minutes.
Fetch the GutenbergGutenbergThe Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc.
https://wordpress.org/gutenberg/ build once per run (#12701) instead of once per job, plus bounded retries on Docker image pulls (#12703). Runs needing a rerun to go green roughly halved, from ~68% to ~36%.
Source: measured per run from the GitHub Actions APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. (job counts and durations, and rerun counts) across comparable runs before / after the changes.
Pilot a dedicated larger-runner pool for use during release windows to help with concurrency issues (more on that in a future update).
Note: The PHPUnit tests themselves could be further tuned. The trims above cut job count, not job duration—so we could give more attention to the tests themselves to find more efficiency.
This update sets jQuery.uiBackCompat to be equal to true to ensure that code written for the jQuery 1.11 APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. continues to function as expected. Additionally, $.fn._form, $.ui.ie, $.ui.safeActiveElement, and $.ui.safeBlurhave been removed. WordPress coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. does not use any of these functions, but you should check your code and update it accordingly if it does.
See [62747] for the specific changes and #62757 for more background information.
WordPress 7.1 introduces four filters that allow plugins to customise the execution lifecycle of abilities registered with the Abilities APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways..
The Abilities API previously provided the wp_before_execute_ability and wp_after_execute_ability actions. These actions are useful for observing execution, but they cannot change its behaviour.
The new filters allow developers to:
Short-circuit ability execution.
Transform normalised input.
Apply additional authorisation rules.
Transform or recover an execution result.
These changes were introduced in TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress.ticketticketCreated for both bug reports and feature development on the bug tracker.#64989 and changeset [62397].
Updated execution lifecycle
The filters are applied in the following order:
wp_pre_execute_ability
│
├── short-circuit when an override is returned
↓
WP_Ability::normalize_input()
↓
wp_ability_normalize_input
↓
WP_Ability::validate_input()
↓
WP_Ability::check_permissions()
↓
wp_ability_permission_result
↓
wp_before_execute_ability
↓
Registered execute callback
↓
wp_ability_execute_result
↓
WP_Ability::validate_output()
↓
wp_after_execute_ability
↓
Return result
Input and output transformations occur before their respective schema-validation steps. Transformed values must therefore continue to satisfy the ability’s registered schemas.
The exception is wp_pre_execute_ability, which bypasses the rest of the pipeline completely.
Short-circuiting execution with wp_pre_execute_ability
The wp_pre_execute_abilityfilterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. runs at the beginning of WP_Ability::execute(), before input normalization, validation or permission checks.
/**
* Filters whether to short-circuit ability execution.
*
* @param mixed $pre Precomputed result. Return it unchanged to
* continue normal execution.
* @param string $ability_name Name of the ability.
* @param mixed $input Raw input passed to execute().
* @param WP_Ability $ability Ability instance.
*/
apply_filters(
'wp_pre_execute_ability',
$pre,
$ability_name,
$input,
$ability
);
Returning $pre unchanged allows execution to continue. Returning any other value short-circuits execution and returns that value directly to the caller.
The filter uses a unique internal sentinel as its default. This means that any PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher value—including null, false, or an object—can be used as a legitimate short-circuit result.
The filter can be used for caching, rate limiting, maintenance mode, approval workflows and test mocking.
Temporarily disabling an ability
The filter can short-circuit selected abilities during maintenance without running input validation, permission checks, or the registered callback:
add_filter(
'wp_pre_execute_ability',
function ( $pre, $ability_name, $input, $ability ) {
if ( 'my-plugin/sync-catalog' !== $ability_name ) {
return $pre;
}
if ( ! get_option( 'my_plugin_maintenance_mode', false ) ) {
return $pre;
}
return new WP_Error(
'ability_temporarily_unavailable',
__( 'This operation is temporarily unavailable due to maintenance.', 'my-plugin' ),
array(
'status' => 503,
)
);
},
10,
4
);
Returning $pre unchanged continues normal execution. When maintenance mode is enabled, the WP_Error is returned immediately, and the remaining ability pipeline is bypassed.
Because this filter runs before permission checks and validation, it should make only narrow decisions that do not depend on validated input or the current ability authorisation result.
Transforming input with wp_ability_normalize_input
The wp_ability_normalize_input filter runs inside WP_Ability::normalize_input(), after the method has applied any defaults declared by the input schema.
Add defaults that cannot be expressed through JSONJSONJSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. Schema.
The transformed input is subsequently checked against the ability’s input_schema.
Returning a WP_Error stops execution before input validation, permission checks and the registered callback:
add_filter(
'wp_ability_normalize_input',
function ( $input, $ability_name ) {
if ( 'my-plugin/process-content' !== $ability_name ) {
return $input;
}
if ( my_plugin_rate_limit_exceeded() ) {
return new WP_Error(
'ability_rate_limit_exceeded',
__( 'The ability rate limit has been exceeded.', 'my-plugin' ),
array( 'status' => 429 )
);
}
return $input;
},
10,
2
);
When execution occurs through the Abilities REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/, a WP_Error returned during normalization is now propagated by the REST controller. It defaults to HTTPHTTPHTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. status 400 unless the error specifies another status, such as 422 or 429.
Filtering permission results with wp_ability_permission_result
The wp_ability_permission_result filter runs inside WP_Ability::check_permissions(), after the registered permission_callback has executed.
/**
* Filters the result of an ability permission check.
*
* @param bool|WP_Error $permission Result from permission_callback.
* @param string $ability_name Name of the ability.
* @param mixed $input Input used for the permission check.
* @param WP_Ability $ability Ability instance.
*/
apply_filters(
'wp_ability_permission_result',
$permission,
$ability_name,
$input,
$ability
);
The filter may return:
true to permit execution.
false to deny execution.
A WP_Error to deny execution with a specific error and message.
Any other return value is converted to false.
Because the filter is part of check_permissions(), it also applies when permission checks are performed independently of execute(), including REST API and WP-CLIWP-CLIWP-CLI is the Command Line Interface for WordPress, used to do administrative and development tasks in a programmatic way. The project page is http://wp-cli.org/https://make.wordpress.org/cli/ integrations.
Applying an additional authorisation policy
add_filter(
'wp_ability_permission_result',
function ( $permission, $ability_name, $input, $ability ) {
if ( 'my-plugin/delete-records' !== $ability_name ) {
return $permission;
}
// preserve both false and WP_Error results
if ( false === $permission || is_wp_error( $permission ) ) {
return $permission;
}
if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error(
'ability_additional_permission_required',
__( 'This operation requires administrator access.', 'my-plugin' )
);
}
return true;
},
10,
4
);
Plugins should exercise particular care with this filter because returning true can override a denial from the ability’s original permission_callback.
Transforming results with wp_ability_execute_result
The wp_ability_execute_result filter runs after the ability’s registered execution callback and before output validation.
/**
* Filters the result returned by an ability execute callback.
*
* @param mixed $result Result returned by the execute callback,
* or WP_Error when execution failed.
* @param string $ability_name Name of the ability.
* @param mixed $input Normalized input.
* @param WP_Ability $ability Ability instance.
*/
apply_filters(
'wp_ability_execute_result',
$result,
$ability_name,
$input,
$ability
);
The filtered result is subsequently validated against the ability’s output_schema.
Recovering from selected execution failures
The filter receives WP_Error values produced by the registered callback, so plugins may implement narrowly scoped recovery behaviour:
add_filter(
'wp_ability_execute_result',
function ( $result, $ability_name, $input, $ability ) {
if (
'my-plugin/get-remote-data' !== $ability_name ||
! is_wp_error( $result ) ||
'remote_service_unavailable' !== $result->get_error_code()
) {
return $result;
}
$fallback = my_plugin_get_fallback_data();
/*
* The fallback must conform to the ability's registered
* output_schema because it will be validated after this filter.
*/
return $fallback;
},
10,
4
);
Any recovered value must still conform to the registered output_schema.
New WP_Filter_Sentinel class
WordPress 7.1 also introduces WP_Filter_Sentinel, a reusable marker class loaded alongside WP_Hook.
CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. uses a unique sentinel instance as the default value for wp_pre_execute_ability. Comparing object identity allows Core to distinguish an unchanged default from every possible user-supplied value, including null, false, arrays and arbitrary objects.
Developers using wp_pre_execute_ability do not need to instantiate this class. To continue normal execution, callbacks should simply return the received $pre value unchanged.
Backward compatibility
These changes are additive:
Existing abilities require no changes.
Existing wp_before_execute_ability and wp_after_execute_ability callbacks continue to work.
Ability callbacks and permission callbacks retain their existing behaviour when none of the new filters is used.
Input and output schemas remain the final validation boundaries for normal execution.
Plugins that already provide their own ability-execution hooksHooksIn WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. may wish to evaluate whether some functionality can now use these Core filters. Protocol- or domain-specific hooks can still be layered on top when they need more specialised context.
Summary
WordPress 7.1 adds the following Abilities API filters:
Filter
Purpose
wp_pre_execute_ability
Short-circuit the complete execution pipeline
wp_ability_normalize_input
Transform normalized input before validation
wp_ability_permission_result
Modify or override permission results
wp_ability_execute_result
Transform or recover results before output validation
These filters make the Abilities API more extensibleExtensibleThis is the ability to add additional functionality to the code. Plugins extend the WordPress core software. for AI integrations, automation systems, protocol adapters, authorisation layers and other tools that mediate ability execution.
For additional context, see Trac ticket #64989 and changeset [62397].
The full chat log is available beginning here on Slack.
WordPress Performance TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. tickets
@westonruter highlighted #65634, a minor improvement to the development environment to make it easier to do performance tests so it is more reflective of an actual normal environment, with a small patchpatchA special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing. ready for review.
For #65215, @westonruter shared that there is some feedback on the PR #11790 that has not been actioned yet.
Performance Lab PluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. (and other performance plugins)
@westonruter highlighted PR #2601, which updates wp-coding-standards/wpcs to 3.4.1, and shared that there was an important security release for WPCSWordPress Community SupportA public benefit corporation and a subsidiary of the WordPress Foundation, established in 2016.. While it has been applied to the Performance repo, anyone with other repositories using an older version should update as soon as possible.
@mukesh27 shared that work has been ongoing over the past few weeks on accurate sizes for the Gallery blockBlockBlock is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. and that the full PR will soon be ready for review.
@b1ink0 asked for feedback on a comment in PR #2336. @westonruter shared that it has been added to saved items.
The live meeting will focus on the discussion for upcoming releases, and have an open floor section.
The various curated agenda sections below refer to additional items. If you have ticketticketCreated for both bug reports and feature development on the bug tracker. requests for help, please continue to post details in the comments section at the end of this agenda or bring them up during the dev chat.
Announcements 📢
Note: Dev Chat has been moved to Tuesdays at 15:00 UTC for the duration of the 7.1 release cycle.
7.1 BetaBetaA pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 4 is scheduled for release on Wednesday, July 29, at 15:00 UTC in core
New 7.1 Dev Notesdev noteEach important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase.:
The discussion section of the agenda is for discussing important topics affecting the upcoming release or larger initiatives that impact the CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. Team. To nominate a topic for discussion, please leave a comment on this agenda with a summary of the topic, any relevant links that will help people get context for the discussion, and what kind of feedback you are looking for from others participating in the discussion.
Any topic can be raised for discussion in the comments, as well as requests for assistance on tickets. Tickets in the milestone for the next major or maintenance release will be prioritized.
Please include details of tickets / PRs and the links in the comments, and indicate whether you intend to be available during the meeting for discussion or will be async.
WordPress 7.1 introduces a new background.gradientblockBlockBlock is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. support. It gives blocks a gradient control in the Background panel of the block inspector. Unlike the existing gradient support, it can be combined with a background image so the two render together.
GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ issue:#32787 | PR:#75859
Background
Until now, the only way to apply a gradient to a block was through the Color panel’s color.gradient support. That value is stored at style.color.gradient and rendered as a backgroundCSSCSSCascading Style Sheets. shorthand.
The background shorthand resets every background property, including background-image. This meant a gradient set through color.gradient would conflictconflictA conflict occurs when a patch changes code that was modified after the patch was created. These patches are considered stale, and will require a refresh of the changes before it can be applied, or the conflicts will need to be resolved. with, and override, any background image on the same block. A block could show a gradient or an image, but not both.
What changed
A new background.gradient block support is registered. It stores its value at style.background.gradient, separate from the existing style.color.gradient.
The key difference is that the new support renders through the background-image longhand property instead of the background shorthand. Because it avoids the shorthand, it no longer resets the other background properties. The style engine can then output the gradient and any background image as comma-separated values in a single background-image declaration:
Block-level values set in the editor override theme defaults, following the same cascade as other block supports.
How it works
Frontend output. Server-side rendering in the background block support reads the gradient value and passes it, together with any background image, to the style engine. The engine merges them into one comma-separated background-image value and injects the result as an inline style on the block wrapper. Serialization for the image and the gradient is checked independently, so a block can skip one while still rendering the other.
Sanitization. Previously, safecss_filter_attr() stripped a background-image value that mixed a gradient function with a url(). In WordPress 7.1, safecss_filter_attr() is updated to allow these combined gradient + url() values, so no additional filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. is required.
Relationship to color.gradient
background.gradient is a separate support from color.gradient. Existing blocks that use color.gradient are unchanged and continue to work exactly as before.
This new support also lays the groundwork for eventually migrating gradient handling from color.gradient to background.gradient across blocks, giving a single, more capable background styling system. That migrationMigrationMoving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. is not part of this change.
Backwards compatibility
These are additive changes. No existing blocks are broken, and no action is required for most blocks and themes. Blocks that do not opt in to background.gradient behave exactly as they did before, including any current use of color.gradient.
Summary
Item
Value
block.json support key
supports.background.gradient
Style storage path
style.background.gradient
theme.json path
styles.background.gradient (and per block)
Rendered CSS property
background-image (comma-separated with any image)
CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. adopters (7.1)
WordPress 7.1 introduces a minWidth dimension blockBlockBlock is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. support, letting blocks opt in to setting a minimum width. This follows the same pattern as the existing minHeight support.
GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ issue:#76525 | PR:#76949
Background
Blocks already support several dimension properties: height, minHeight, and width. There was no matching control for a minimum width. Setting a floor on a block’s width is a common CSSCSSCascading Style Sheets. need. For example, you may want a container or layout element to stay usable and not collapse below a certain size on smaller viewports.
Until now, achieving this required custom CSS or a custom block style, since the design tools did not expose a min-width option. This release handles it natively through a new block support.
What changed
A new minWidth feature is registered under the existing dimensions block support. When a block opts in, a “Minimum width” control appears in the Dimensions panel, alongside the existing minimum height control. The value is applied as the CSS min-width property, and it supports dimension presets (dimensionSizes) where a theme provides them.
How to use it
A block opts in through its block.jsonsupports, the same way it opts in to minHeight:
If the active theme defines dimensionSizes presets, the control offers those presets, and selecting one applies the matching --wp--preset--dimension--{slug} custom property.
Where the control appears
The minimum width control follows the same visibility rules as other optional design tools:
In the block inspector, the control is not shown by default. A block must opt in through __experimentalDefaultControls to show it automatically. Otherwise, you reveal it from the panel’s options menu (the three-dots menu on the Dimensions panel headerHeaderThe header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes.).
In Global Styles (Site Editor), the control is shown by default.
Block-level values set in the editor override the theme defaults, following the same cascade as other block supports.
Backwards compatibility
These are additive changes. No existing blocks are broken, and no action is required for most blocks and themes. Blocks that do not opt in behave exactly as before. Themes that do not enable the setting see no change.
WordPress 7.0 added a built-in set of SVG icons that the blockBlockBlock is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor and the coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress./icon block can use. In 7.1, this becomes a proper, public APIAPIAn API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.: you can now add your own icons, group them, render them on the server, and read them over the REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”)
https://developer.wordpress.org/rest-api/.
Icons are registered in one place and can then be used in several: the editor, the REST API, and your own PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher. This note covers the pieces you’ll work with:
Creating and removing icon collections.
Adding and removing individual icons.
Browsing icons by collection in the Icon block’s picker.
Rendering an icon in PHP with wp_get_icon().
The REST API endpoints for collections and icons.
Icon collections
Every icon belongs to a collection. A collection is just a named group of icons, and its name becomes a prefix: that’s what makes core/plus different from my-plugin/plus. This lets icons from different sources — WordPress, a pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party., or a third-party icon set — live side by side without clashing.
WordPress registers one collection by default, called core, with its own bundled icons.
Creating a collection
An icon can only be added to a collection that already exists, so start by registering the collection with wp_register_icon_collection().
The first argument is the collection name. It must start and end with a lowercase letter or digit, and in between may contain lowercase letters, digits, hyphens, and underscores. The second is an array with a required label and an optional description.
Removing a collection
Use wp_unregister_icon_collection() with the collection name. Removing a collection also removes every icon in it, so you don’t need to remove the icons one by one. Run this on the init hook, at a later priority than the registration so the collection already exists:
Every icon name has the form collection/icon-name, for example my-plugin/star. The collection must already be registered when you register the icon.
The icon-name part follows the same rule as a collection name: it must start and end with a lowercase letter or digit, and in between may contain lowercase letters, digits, hyphens, and underscores.
Adding icons
Register an icon with wp_register_icon(). You give it a label and the SVG itself — either inline as a string (content) or as an absolute path to an .svg file (file_path). Use one or the other, not both.
Like the other registration functions, wp_register_icon() returns true on success and false on failure, emitting a _doing_it_wrong() notice that explains why. Registration fails for an invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. name, a name that isn’t namespaced as collection/icon-name, a collection that isn’t registered, a duplicate icon, a missing label, unsupported argument keys, or providing neither content nor file_path (or both).
The SVG is sanitized through wp_kses against a small allowlist: only the <svg>, <path>, and <polygon> elements survive, each limited to a fixed set of attributes. Anything outside that subset — other elements, inline styles, scripts, or event handlers — is stripped. This allowlist is intentionally conservative and may be broadened in the future to cover more shape elements and attributes; see https://github.com/WordPress/gutenberg/pull/75550 for the ongoing work.
Note that file_path is read lazily: the file isn’t opened at registration, only when the icon’s content is first needed, during REST retrieval or rendering. So registration can succeed even if the path is wrong; a missing or unreadable file surfaces later as empty content, not as a registration error. Make sure the path resolves on the environment where the icon is used.
Icons can go into any registered collection. Most of the time, registering them under your own collection keeps them clearly separated from core’s.
function my_plugin_register_icons() {
// Register a custom collection first, then add icons to it.
wp_register_icon_collection(
'my-plugin',
array(
'label' => __( 'My Plugin Icons', 'my-plugin' ),
)
);
// An icon from an inline SVG string.
wp_register_icon(
'my-plugin/star',
array(
'label' => __( 'Star', 'my-plugin' ),
'content' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2l2.9 6.9 7.1.6-5.4 4.7 1.6 7L12 18l-6.2 3.2 1.6-7L2 9.5l7.1-.6z" /></svg>',
)
);
// An icon from an .svg file shipped with the plugin.
wp_register_icon(
'my-plugin/heart',
array(
'label' => __( 'Heart', 'my-plugin' ),
'file_path' => plugin_dir_path( __FILE__ ) . 'icons/heart.svg',
)
);
}
add_action( 'init', 'my_plugin_register_icons' );
Removing an icon
Remove a single icon by name with wp_unregister_icon(), again on the init hook after the icon has been registered. Like the registration functions, it returns true on success and false on failure, emitting a _doing_it_wrong() notice; the only failure case is that the icon isn’t registered.
To remove every icon in a collection at once, remove the collection instead (see Removing a collection).
Icon block enhancementenhancementEnhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature.
The icon picker in the core Icon block now groups icons by collection, so custom icons from plugins and themes appear alongside the core ones.
Each collection has its own tab, plus an “All” tab covering every collection at once. Search filters the selected collection; use the All tab to search across collections. The search query is preserved when switching tabs.
The block itself picked up a few more changes:
Flip and rotate. The toolbar now has controls to flip the icon horizontally or vertically, and a button that rotates it 90 degrees at a time.
Default icon. A newly inserted Icon block now starts with core/info instead of an empty placeholder.
Server rendering via wp_get_icon(). The block’s server-side render now delegates to wp_get_icon() to produce the SVG markup, so a block-rendered icon and one you print yourself with wp_get_icon() go through the same code path.
Rendering an icon in PHP
Use wp_get_icon() to get the SVG markup for any registered icon, ready to print:
// A decorative icon at the default 24px size.
echo wp_get_icon( 'core/plus' );
// A 32px icon with an accessible label and an extra CSS class.
echo wp_get_icon(
'my-plugin/star',
array(
'size' => 32,
'label' => __( 'Featured', 'my-plugin' ),
'class' => 'my-plugin-star',
)
);
The first argument is the icon name. If it isn’t registered, you get an empty string. The optional second argument accepts:
size — Width and height in pixels. Defaults to 24. Pass null to keep the SVG’s own size.
class — Extra CSSCSSCascading Style Sheets. class names for the <svg> element.
label — An accessible label. If you provide one, the icon is announced to screen readers; if you leave it out, the icon is treated as decorative and hidden from them.
Styling icons
Styling ReactReactReact is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces.
https://reactjs.org icons from @wordpress/icons
Since version 15.0.0, each icon declares fill="currentColor" on its outer <svg>, so a React-rendered icon follows the current text color out of the box. By default the icon inherits color from its ancestors. To apply a different color, set color rather than fill — pass style={ { color } } to the icon:
import { Icon, plus } from '@wordpress/icons';
<Icon icon={ plus } style={ { color: '#3858e9' } } />;
Styling the SVG returned by wp_get_icon()
This markup is sanitized on registration, and the allowlist keeps fill only on the <path> and <polygon> shapes — not on the outer <svg> — and doesn’t permit stroke anywhere, so a stroke-based icon loses its stroke and you should stick to fill-based shapes for now. (This is a current limitation: the allowlist may be relaxed in the future to cover stroke and other attributes; see https://github.com/WordPress/gutenberg/pull/75550 for the ongoing work.) One upshot is that the fill="currentColor" the React icons carry on their <svg> does not survive here, and wp_get_icon() doesn’t add one. That has two consequences:
Inside the Icon block, coloring still works, because the block’s stylesheet sets fill: currentColor on .wp-block-icon svg. A block-rendered icon therefore follows the text color.
A standalone wp_get_icon() call returns bare markup with no such rule, so by default it renders in the SVG’s own fill (black), not the surrounding text color.
To make a standalone icon follow the text color, you have two options.
Supply your own CSS. Render the icon with a class (wp_get_icon() puts it on the <svg>), then set fill on it — since fill is inherited, it cascades to the shapes:
Alternatively, put fill="currentColor" on the shape when you register the icon. The allowlist keeps fill on <path> and <polygon>, so it survives sanitization and the icon carries its own color behavior wherever it’s rendered:
The editor reads icons and collections over the REST API, and your own code can too. These endpoints are read-only: every route is a GET, so you can browse registered icons and collections but can’t register or change them over REST. All endpoints are under wp/v2 and require an authenticated user who can edit_posts, or who holds the equivalent edit capabilitycapabilityA capability is permission to perform one or more types of task. Checking if a user has a capability is performed by the current_user_can function. Each user of a WordPress site might have some permissions but not others, depending on their role. For example, users who have the Author role usually have permission to edit their own posts (the “edit_posts” capability), but not permission to edit other users’ posts (the “edit_others_posts” capability). for any REST-visible (show_in_rest) post type.
Collections:
GET /wp/v2/icon-collections — All collections.
GET /wp/v2/icon-collections/<collection> — A single collection.
Each collection is returned as an object with slug, label, and description. For example, GET /wp/v2/icon-collections/core returns:
GET /wp/v2/icons — All icons. (introduced in 7.0 with the name, label, and content fields and the search parameter; 7.1 adds the collection field and parameter)
GET /wp/v2/icons/<collection> — Icons in one collection. (new in 7.1)
GET /wp/v2/icons/<collection>/<name> — A single icon. (introduced in 7.0)
Each icon is returned as an object with name (the full collection/icon-name), label, content (the sanitized SVG markup), and collection (the slug of the collection it belongs to). For example, GET /wp/v2/icons/core/plus returns:
The icon list also accepts two query parameters: search to filterFilterFilters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. by name or label, and collection to limit results to one collection. For example:
WordPress 7.1 continues to use ReactReactReact is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces.
https://reactjs.org 18.3
React 19 upgrade won’t be a part of WordPress 7.1. After briefly enabling it in GutenbergGutenbergThe Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc.
https://wordpress.org/gutenberg/ we discovered unexpected incompatibilities in how old and new version of React interact with each other, and in the ways how plugins use React, and we were forced to revert the change. We’ll need a considerable testing period where we improve and fine-tune the compatibility layer that allows the existing plugins to run seamlessly.
Experimental flag in Gutenberg
Instead, there is a new experiment in the Gutenberg pluginPluginA plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. (since version 23.4) that enables React 19 on your WordPress site, intended for testing plugin compatibility. To enable the experiment, install the Gutenberg plugin and check a checkbox on the Gutenberg Experiments page (under Settings › Gutenberg):
Testing plugins
Testing a plugin compatibility generally means trying to use all parts of the plugin that uses React, typically Gutenberg blocks and extensions, and also custom WP Adminadmin(and super admin) pages, and verifying that the UIUIUser interface is not broken and there are no errors logged in the browser console.
What kind of errors to look for
Typical failure modes for plugins are:
Bundling the react/jsx-runtime code directly in the plugin JavaScriptJavaScriptJavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser.
https://www.javascript.com code instead of using the “externalized” react-jsx-runtime script provided by WordPress itself. Such bundling leads to a mixture of React 18 (bundled) and React 19 (provided by WordPress) running together and passing data structures created by the old version to the new runtime. If everyone was bundling their JavaScript correctly, the majority of compat issues wouldn’t happen at all.
Using really old React features that were removed in React 19, after being deprecated for a long time (at least 6 years). String refs, default props on function components, legacy ways of defining context, … Some of them we’re polyfilling in the compat layer. A more detailed overview can be found in the “Removed APIs” section of an earlier post about the React 19 upgrade.
Everyone is invited to test and update their plugins, and report issues in the Gutenberg GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ repo.
You must be logged in to post a comment.