Update to content only editing filter namespace

This dev notedev note Each 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. is a follow up to a previous dev note: Content only editing and other locking updates.

The GutenbergGutenberg The 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/ PR, #43037, which introduced the feature, added a filterFilter Filters 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. hook with the same namespace ('core/style/with-block-controls') as an existing filter hook that implements block support style controls.

addFilter(
	'editor.BlockEdit',
	'core/style/with-block-controls',
	withBlockControls
);

The risk of having two hooksHooks In 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. with the same namespace is that any attempt to remove the filter will, possibly unintentionally, affect them both.

removeFilter( 'editor.BlockEdit', 'core/style/with-block-controls' );

The BlockBlock Block 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 documentation states the following:

One notable difference between the JSJS JavaScript, a web scripting language typically executed in the browser. Often used for advanced user interfaces and behaviors. and PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher hooks APIAPI An 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. is that in the JS version, addAction() and addFilter() also need to include a namespace as the second argument. Namespace uniquely identifies a callback in the form vendor/pluginPlugin A 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/function.

https://developer.wordpress.org/block-editor/reference-guides/packages/packages-hooks/#the-global-instance

A subsequent Gutenberg PR #46344 has renamed the filter hook namespace for the content lock filter hook to 'core/content-lock-ui/with-block-controls'. This now makes the namespace unique within the context of the Block Editor.

addFilter(
	'editor.BlockEdit',
	'core/content-lock-ui/with-block-controls',
	withBlockControls
);

No functionality has been affected. The change will ship with Gutenberg 14.8.

Props to @talldanwp for technical assistance and @milana_cap, @aaronrobertshaw and @andrewserong for reviewing.

#dev-notes, #dev-notes-6-2, #gutenberg

Postponed to WP 6.2: Escaping Table and Field names with wpdb::prepare()

Support for %i to escape Table and Field names was postponed to 6.2, see:
https://make.wordpress.org/core/2022/10/08/escaping-table-and-field-names-with-wpdbprepare-in-wordpress-6-1/

A problem was found during RC5, where some extensions use field LIKE "%%%s%%", and expect the %s to remain unquoted.

This is undocumented behaviour. Officially the only time placeholders should not be quoted (for backwards compatibility reasons) is when using numbered or formatted string placeholders (this is unsafe, and should be avoided).

In this case, the first %% results in a literal "%", but this goes on to affect the %s.

For reference, developers should rely on wpdb::prepare() to quote all variables, so mistakes cannot be made. In this case it’s recommended to use something like the following:

$wpdb->prepare( 
     'field LIKE %s', 
     '%' . $wpdb->esc_like( $var ) . '%' );

Thanks to @AlanP57 for reporting, @hellofromtonya and @sergeybiryukov for reverting the patchpatch A 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., @azaozz and @bph for helping document this, and everyone else for generally helping out.

#6-1, #dev-notes, #dev-notes-6-1, #wpdb

Multisite registration and activation pages have new HTML and CSS

In WordPress 6.1, the forms for the wp-signup.php and wp-activate.php pages have several enhancements to both the markup and the styles.

AccessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility)-related improvements

Indicating relationships:

  • Fieldsets, with visible legend text, group the radio buttons.
  • Form field description information connects to its related field with aria-describedby.
  • When present, error messages also connect to their field with aria-describedby. The generic error has an ID in case custom fields should refer to that.

Preventing errors:

  • Required text fields have the required attribute.
  • The Site Name label indicates that users should enter the subdirectory only, and the Site Domain is only the desired subdomain.
  • The Username field’s description text now specifies that letters need to be lowercase.

Color contrast:

  • If the activation page has an error message, its default dark gray text color contrasts against the light background.
  • The default style for links within the registration page’s bordered message (.mu_alert) includes an underline and matches the text color of the rest of the message. For example, Twenty Twenty-One’s dark mode assigns a light link color, so the new style makes it readable and identifiable as a link. If a theme uses a bottom border or box-shadow on links, however, this underline could be inappropriate.
“Options page” link had light gray text in Twenty Twenty-One’s dark mode
Links were sometimes difficult to see
“Options page” link is in the same dark gray text as the rest of the message
Links match the surrounding text color, underlined, in 6.1

New elements and styles for the registration page form

  • The fieldset and legend elements reset margin, padding and border properties.
  • The legend styles are consistent with the default label font size, weight and margins.
  • Radio buttons are inside paragraphs without a top margin, following the legend.
  • Text input fields and the submit button, which were set to 100% width plus padding, are only as wide as their container now.
screenshot of account setup page in WordPress 6.1
New account setup, step 1, allowing both sites and usernames

When people create an account:

  • Descriptive text for the Username and Email Address is inside paragraph tags. Because these immediately follow the input, the paragraphs do not have a top margin.
  • Options for creating a site and/or a username are grouped in a fieldset with a new, visible legend.
  • Elements with the “wp-signup-radio-button” class wrap these options’ radio buttons and their labels, and with “display: block” the options stack vertically.
screenshot of form with Site Name (for subdirectory installations), Site Title, Site Language and Privacy options
Form fields for an administrator (logged in) to create a new site

When an administrator creates a new site:

  • A “wp-signup-blogname” container wraps the Site Name (or Site Domain) input with the domain, so themes could arrange them side-by-side.
  • For right-to-left languages, the domain and its input field remain in the left-to-right direction.
  • The “privacy-introfieldset uses paragraph tags inside it to retain most paragraph styles from the theme.
  • By wrapping “Privacy:” in a “label-headingspan, it appears above the rest of the legend. This text maintains the same default font size and weight given to the legend and label elements.
  • The “Yes” and “No” labels have moved next to the radio buttons, instead of inside them. Without the strong emphasis tags, these can match the default label font weight of 600. If any theme overrides the “.mu_register label.checkbox” selector to block display, that property will need updating to an inline style.
  • In this fieldset, “wp-signup-radio-button” containers remain next to each other, with a small margin between them.

Site activation page styles

screenshot of site activation page with Twenty Twenty theme
  • The activation form’s container is centered, to match the signup page.
  • The input field and submit button cover the full width of the container, with box-sizing: border-box to prevent them from extending beyond 100%.
  • The form and .error selectors now include .wp-activate-container so that the styles do not affect elements in the headerHeader The 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. or footer.

BlockBlock Block 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. themes

This is not new to 6.1, but block themes should continue to include header.php and footer.php template files for these pages. To make a header template more specific to the networknetwork (versus site, blog) pages, its filename can be header-wp-signup.php or header-wp-activate.php.


For more information about the HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. and CSSCSS Cascading Style Sheets. changes, view tickets #40361 and #54344.

Props: Thank you, @ironprogrammer, @webcommsat, @audrasjb and @joedolson, for peer review and editing.

#accessibility, #core-multisite, #dev-notes, #dev-notes-6-1, #multisite, #themes

Global terms removed in WordPress 6.1

Global terms is an old feature from the MU days of WordPress when multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site and single site installs had separate code bases. It has been abandoned and unmaintained for a significant amount of time, and in WordPress 6.1, it has finally and officially been removed.

Here’s a brief timeline of events leading up to this change.

WordPress 3.0 (2010): Phase 1

The first phase of removing global terms was in WordPress 3.0.

  • The user interface for global terms was completely removed in [14854].
  • The “on” switch in CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. was removed in [14880], though plugins were free to call install_global_terms() directly, if they dared.

2010-2022:

  • A Global Terms pluginPlugin A 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 was created and released with the goal of moving the code there from Core. The plugin broke with the release of WordPress 3.5 and has not been updated.
  • With the introduction of term splitting in WordPress 4.2, the feature became even more broken and bugbug A 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.-ridden.
  • When term metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. was introduced in WordPress 4.4 (see #10142), the affects on global terms were (rightfully) not considered. I haven’t actually tested, but it’s safe to say that term meta does not work with global terms, and would cause a number of issues.
  • Searches of the plugin directory show no meaningful usage of the global terms related functions with the exception of global_terms_enabled() (more on this below).

WordPress 6.1 (2022): Phase 2

This release will mark the completion of the second and final phase of removing global terms.

  • All global term related functions have been officially deprecated and will now throw proper deprecated notices (see [54240]).
  • The functions have also been no-opped (no operationed) and calling them will have no effect, except for triggering a deprecated notice. There are a two exceptions which are detailed below.

global_terms() function

This function used to be hooked to the term_id_filter filterFilter Filters 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.. This is no longer the case. However, the function will continue to return the $term_id value passed to it in case it’s being called directly in the wild.

global_terms_enabled() function

This function previously returned a boolean indicating whether global terms were enabled or not. Even though there is almost no usage of this function in the plugin directory, it’s the function with the highest probability of being used.

After [54240], global_terms_enabled() will always return false.

sitecategories database table

Sites that had global terms enabled at one point in time will likely have a sitecategories table in their database. This table will not be touched with these changes. Most sites should be able to safely remove this table.

For more information on this change, see #21734 on TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..

Props @davidbaumwald for reviewing.

#dev-notes, #dev-notes-6-1, #networks-sites

Block API changes in WordPress 6.1

WordPress 6.1 introduces several new BlockBlock Block 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. APIAPI An 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. features available via the block.json file.

As a recap, the block.json file was introduced in WordPress 5.5 and has been encouraged as the canonical way of registering block types since the WordPress 5.8 release. Many of the recent Block API features, including the ones in this post, depend on block.json being available on the server.

PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher templates for rendering blocks

Before WordPress 6.1, the main output of a block would often be generated in either a JavaScriptJavaScript JavaScript 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/. save function, or in a PHP render_callback function.

WordPress 6.1 adds a third way: a separate PHP template file. The path can be specified via the render property of block.json:

{
    "render": "file:./render.php"
}

If you don’t have a render_callback setting specified, then the template is used instead. It behaves similarly, but feels much more like traditional WordPress template handling.

The template path is prefixed with file: and relative to the location of the block.json file, following the npm specification.

The render.php template could look like this:

<p <?php echo get_block_wrapper_attributes(); ?>>
    <?php esc_html_e( 'Hello from a dynamic block!', 'my-plugin' ); ?>
</p>

Note: The entire file is used as a template, so there’s no need to define additional wrapping functions.

The following variables are available inside the template:

  • $attributes (array): The block attributes.
  • $content (string): The block default content.
  • $block (WP_Block): The block instance.

Use multiple scripts per block

The WordPress 6.1 version enables defining multiple script files in all relevant block.json entries: editScript, script, and viewScript. (Trac #56408) It’s now possible to pass a script handle registered with the wp_register_script function, a path to a JavaScript file relative to the block.json file, or an array with a mix of both:

{
    "editorScript": "file:./index.js",
    "script": "file:./script.js",
    "viewScript": [ "file:./view.js", "example-shared-view-script" ]
}

WordPress maintains a degree of backwards compatibility by passing along only the first (string) item to any existing code working with these values.

Note: Processing a single string requires a different code than processing an array of strings. Therefore, the WP_Block_Type class and the /wp/v2/block-types REST APIREST API The 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/. endpoint deprecate accessing string values through their old names: editor_script, script, view_script, editor_style, and style.

The full array of scripts can be accessed via the following new properties of the WP_Block_Type class and the /wp/v2/block-types REST API endpoint:

  • editor_script_handles,
  • script_handles,
  • view_script_handles,
  • editor_style_handles, and
  • style_handles.

Furthermore, the scripts and styles registered in block.json will automatically be loaded for static and dynamic blocks in WordPress 6.1. Previously, the dynamic blocks were expected to register their assets.

Combined with the support for multiple stylesheets per block shipped with WordPress 5.9, this change enables developers to use multiple entries for all supported asset types.

Import individual coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks from @wordpress/block-library

The import of individual core blocks (Pull request #42258) from the @wordpress/block-library npm package was enabled to help developers reduce the bundle size of their applications. Prior to this change, the use of a single core block required pulling in the entire set.

Individual core blocks can be imported in three different ways:

// You can import and automatically register the block:
import '@wordpress/block-library/build-module/verse/init';

// Or you can automatically register the block and reuse the reference:
import verseBlock from '@wordpress/block-library/build-module/verse/init';

// Or you can import the init function without registering the block…
import { init } from '@wordpress/block-library/build-module/verse';

// …and then register the block when needed:
const verseBlock = init();

Props to @gziolo, and @revgeorge for technical review, to @bph and @webcommsat for final review.

#6-1, #dev-notes, #dev-notes-6-1, #developer-documentation

Content only editing and other locking updates

WordPress 6.1 comes with content-only editing for blocks, patterns, and templates, as well as a template lock inheritance for the Column blockBlock Block 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..

Almost any layout using the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks can be composed and shared as a pattern. End users may have found they could accidentally break these layouts or use them in an unexpected way. Previously, the experience of using patterns was not on par with having a specific block for a complex layout.

With WordPress 6.1, a new experimental type of locking has been added called “contentOnly”. This locking method can be used by any pattern or block. When enabled, the users can only change the nested content inside the block/pattern. The block structure starts behaving as a single unit where the block hierarchy is entirely hidden. The user can only change text and media URLs in the blocks. 

Additionally, block types without content are hidden from the List View and are unable to gain focus within the block list. This makes it harder to break the expected layout.

In locked mode, the inspector controls of the blocks are also disabled. Instead, the sidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. only shows a list of content blocks a user can change.

For now, users still have the freedom to leave this locked mode by pressing modify. When modify is pressed, the block editor shows the hierarchy, and the user has complete control. For now, any user can press the modify button. In the future, it may depend on the capabilities of the user.

Content only editing in a block

The core blocks that support content locking are column, cover, and group.

To use content locking, the templateLock attribute of one of the previously referred blocks should be set to “contentOnly”.

In the following pattern, only the content of the paragraph blocks can be edited. A user would not view the spacer block in between.


Paragraph 1

Paragraph 2

Using as custom post-type template locking

The new content-only locking can also be used as custom post-type template locking, like all the other locking methods that exist.

Example:

function myplugin_register_template() {
    $post_type_object = get_post_type_object( 'post' );
    $post_type_object->template = array(
        array(
			'core/group',
			array(),
			array(
				array(
					'core/paragraph',
					array( 'placeholder' => 'Add Description...',
					)
				)
			)
		),
    );
    $post_type_object->template_lock = 'contentOnly';
}
add_action( 'init', 'myplugin_register_template' );

Visit pull request: #43037 and Block Template Documentation

Global template_lock inheritance in the column block

The block template defines a default list of blocks in an editor session. To prevent manipulation of the block list, all blocks can be locked by the template_lock property.

However, in column blocks, the editor would crash on certain operations because it would initialize the lock status defined in the block template. To resolve this issue and to be more consistent about template lock status inheritance, column blocks now inherit the lock status of block templates.

For more information visit #42677.

Props to @wildworks contribution, @bph and @webcommsat for reviews.

#6-1, #dev-notes, #dev-notes-6-1

Simplified data access with new React hooks in WordPress 6.1

The @wordpress/core-data JavaScriptJavaScript JavaScript 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/. package in 6.1 ships new ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. hooksHooks In 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. that make accessing WordPress data easier than before.

useEntityRecords

With useEntityRecords developers, can fetch a list of records with a single hook call:

useEntityRecords( 'postType', 'page' )

Below is what it looks like when used in a React component:

import { useEntityRecord } from '@wordpress/core-data';
 
function PageTitlesList() {
   const pages = useEntityRecords( 'postType', 'page' );
 
   if ( pages.isResolving ) {
      return 'Loading...';
   }
 
   return (
      <ul>
         {pages.records.map(( page ) => (
            <li>{ page.title }</li>
         ))}
      </ul>
   );
};
 
// Rendered in the application:
// <PageTitlesList />

In the above example when PageTitlesList is rendered, the list of records and the resolution details will be retrieved from the store state using getEntityRecords(), or resolved if missing.

The useEntityRecords accepts four arguments:

  • kind (string) – Kind of the entity, e.g. root or a postType.
  • name (string) – Name of the entity, e.g. plugin or a post.
  • queryArgs (object) – Optional HTTPHTTP HTTP 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. query to pass to the requested APIAPI An 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. endpoint, e.g. { "per_page": 10 }
  • options (object) – Optional hook options. Currently, the only supported option is enabled and determines whether the records will be requested.

It returns an object with the following properties:

  • records (array) – The requested entity records
  • isResolving (boolean) – Are these records being resolved at the moment?
  • hasResolved (boolean) – Have these records resolved already?
  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR

useEntityRecord:

Developers can retrieve a single record using the useEntityRecord hook:

import { useEntityRecord } from '@wordpress/core-data';

function PageTitleDisplay( { id } ) {
	const page = useEntityRecord( 'postType', 'page', id );

	if ( page.isResolving ) {
		return 'Loading...';
	}

	return page.title;
}

// Rendered in the application:
// <PageTitleDisplay id={ 13 } />

In the above example, when PageTitleDisplay is rendered, the page and the resolution details will be retrieved from the store state using getEntityRecord(), or resolved if missing.

The useEntityRecord hook accepts four arguments:

  • kind (string) – Kind of the entity, e.g. root or a postType.
  • name (string) – Name of the entity, e.g. plugin or a post.
  • recordId (string|number) – The ID of the requested entity record.
  • options (object) – Optional hook options. Currently, the only supported option is enabled and determines whether the records will be requested.

It returns an object with the following properties:

  • record (object|null) – The resolved entity record.
  • isResolving (boolean) – Is the record being resolved at the moment?
  • hasResolved (boolean) – Has the record already resolved already?
  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR.
  • hasEdits (boolean) – Does the record have any in-browser edits?
  • editedRecord (object|null) – The record with any in-browser edits applied.
  • edit (function) – Applies the in-browser edits to the edited entity record.
  • save (function) – Persist the in-browser edits to the server.

Below is an example showcasing the editing capabilities provided by useEntityRecord:

import { useDispatch } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { TextControl } from '@wordpress/components';
import { store as noticeStore } from '@wordpress/notices';
import { useEntityRecord } from '@wordpress/core-data';
 
function PageRenameForm( { id } ) {
 	const page = useEntityRecord( 'postType', 'page', id );
 	const { createSuccessNotice, createErrorNotice } =
 		useDispatch( noticeStore );
 
 	const setTitle = useCallback( ( title ) => {
 		page.edit( { title } );
 	}, [ page.edit ] );
 
 	if ( page.isResolving ) {
 		return 'Loading...';
 	}
 
 	async function onRename( event ) {
 		event.preventDefault();
 		try {
 			await page.save();
 			createSuccessNotice( __( 'Page renamed.' ), {
 				type: 'snackbar',
 			} );
 		} catch ( error ) {
 			createErrorNotice( error.message, { type: 'snackbar' } );
 		}
 	}
 
 	return (
		<form onSubmit={ onRename }>
			<TextControl
				label={ __( 'Name' ) }
				value={ page.editedRecord.title }
				onChange={ setTitle }
			/>
			<button type="submit">{ __( 'Save' ) }</button>
		</form>
 	);
}
// Rendered in the application:
// <PageRenameForm id={ 1 } />

In the above example, updating and saving the page title is handled via the edit() and save() mutation helpers provided by useEntityRecord();

useResourcePermissions

Developers can check the current user’s permissions using the useResourcePermissions hook:

import { useResourcePermissions } from '@wordpress/core-data';

function Page({ pageId }) {
	const pagePermissions = useResourcePermissions( 'pages', pageId );

	if ( pagePermissions.isResolving ) {
		return 'Loading ...';
	}

	return (
        <div>
			{pagePermissions.canCreate
				? (+ Create a new page)
				: false}
			{pagePermissions.canUpdate
				? (Edit page)
				: false}
			{pagePermissions.canDelete
				? (Delete page)
				: false}
			// ...
        </div>
	);
}

// Rendered in the application:
// <Page pageId={ 15 } />

In the above example when the Page is rendered, the appropriate record-level page permissions and the resolution details will be retrieved from the store state using the canUser() selector, or resolved if missing.

In the following example, the PagesList component requests permissions for the pages collection and not a specific page record:

import { useResourcePermissions } from '@wordpress/core-data';

function PagesList() {
   const pagesPermissions = useResourcePermissions( 'pages' );

   if ( pagesPermissions.isResolving ) {
      return 'Loading ...';
   }

   return (
      <div>
         {pagesPermissions.canCreate
            ? (+ Create a new page)
            : false }
         // ...
      </div>
   );
}

// Rendered in the application:
// <PagesList />

The useResourcePermissions hook accepts two arguments:

  • resource (string) – The resource in question, e.g., media.
  • id (string|number) – Optional ID of a specific resource entry, e.g., 10.

It returns an object with the following properties:

  • status (string) – Resolution status. One of: IDLE, RESOLVING, SUCCESS, or ERROR
  • isResolving (boolean) – Is the record being resolved at the moment?
  • hasResolved (boolean) – Has the record already resolved?
  • create (boolean) – Can the current user create new resources of this type?
  • read (boolean) – Can the current user read resources of this type?
  • update (boolean) – Only if id is provided. Can the current user update the requested resource?
  • delete (boolean) – Only if id is provided. Can the current user delete the requested resource?

Documentation: @wordpress/core-data packages

Props for review @bph, @gziolo, and @webcommsat

#6-1, #wordpress-data, #dev-notes, #dev-notes-6-1, #editor

Reference Styles values in theme.json

With WordPress 6.1, theme developers can style elements with references from other settings.

Theme designs often require consistency in the styles applied to blocks. This can be achieved by setting Styles properties which are inherited by blocks using the inheritance of the CSSCSS Cascading Style Sheets. cascade. In some cases blocks want to apply settings from Styles to a different property of the blockBlock Block 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. – for example the button element might want to use the global text color for its background color and the global background for its text color.

To solve this problem, themes need to be able to share Styles settings with blocks. This will make it easier for users to update these shared properties across all their blocks. Again, as example for button element the developer wants to use the text color for its background. If the button element is set up as in the example above, then when a user edits the global text color, the background color of their buttons will also be updated, too.

To achieve this, a new ref property was added to theme.jsonJSON JSON, 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. which allows one property to set itself to the value of another, for example defining this for button elements:

"elements": {
	"button": {
		"color": {
			"background": {
				"ref": "styles.color.text"
			},
			"text": {
				"ref": "styles.color.background"
			}
		}
	}
}

Styles will convert {ref: "styles.color.background"} the value at: styles > color > background in theme.json.

Limitations

It is currently only possible to use ref to get one value from theme.json; a ref value cannot point to another ref. This also prevents circular refs from causing problems.

Props to @bph and @webcommsat for review of this post.

#6-1, #dev-notes, #dev-notes-6-1, #styles, #themes

WordPress 6.1 Accessibility Improvements

Thank you to @joedolson and @alexstine for collaborating to write this post.

With WordPress 6.1 around the corner, this post brings together the many accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) improvements and fixes to look forward to that might be hard to discover amongst the details of 500+ bugs and enhancements. As always, there’s more work to be done with accessibility requiring an ongoing effort and commitment. 

If you’re interested in helping with this work, please join the #accessibility channel in Make SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/. (need a slack account to view) and check out how you can get involved. There are numerous ways to get involved in this important work including testing, giving accessibility feedback, and creating PRs to address feedback.

Themes

Most notably, 6.1 will see the introduction of both Twenty Twenty-Two and Twenty Twenty-Three marked as accessibility ready, making them both the first default blockBlock Block 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. themes to do so (and only default block themes). This helps open up more folks to the world of block themes and broader site editing features.

WP Adminadmin (and super admin) Screens

Across the many screens in WP Admin, improvements abound. Changes range from improvements in color contrast on the pluginPlugin A 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 screen during recovery mode, to a switch from a text input to a textarea field in the media library, so users are better able to see the content of the field while editing. 

Login and Registration

To better call attention to the many improvements to this form, this section has been pulled out of the WP Admin Screen section. While this is a lesser used interface, the accessibility improvements are quite significant for this release, addressing many longstanding problems. This includes proper labels for required fields, explicitly associating errors with input fields so folks know what actions to take where, improved labels for radio buttons, and more. 

Site Editor/Template Editor

Even though the Site and Template editors both use blocks, there are some specific accessibility challenges for these new interfaces in a site editing world. More work is needed and, if you’re keen to help, please join the FSE Outreach Program where you can go through calls for testing to provide feedback, find bugs, and more. 

Navigation block

The navigation block continues to be a powerful and complex block, especially in the world of block themes. While there are fallbacks and an improved menu management experience to look forward to in this release, there is also a nice set of accessibility related fixes to make this necessary block usable for more people in more situations. 

General Block Editor (other blocks, writing flow, components, etc)

This section covers a wide range of items including everything from improvements to additional blocks, like a focus loss fix for the Table block, and larger improvements to functionality like the Tools Panel. Specifically, the Tools Panel helps power part of the experience of using the numerous design tools present in more blocks for this release. It’s what you’d interact with to interact with more tools or reset changes. Improving the accessibility of this single tool has a cascading impact by improving the experience everywhere it’s used.  

Comments

Comments now include proper contextual attributes for autocomplete fields, proper labels for the visible text describing required fields, and improved accessibility (and translatability) of the logged in as link.

#6-1, #accessibility, #dev-notes, #dev-notes-6-1

Miscellaneous REST API improvements in WordPress 6.1

Search REST resources by ID across subtypes

WordPress 6.1 includes an enhancementenhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. to the search controller, #56546, which makes it possible to retrieve a term or post object over the REST APIREST API The 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/. without knowing anything but that resource’s ID and object type.

get_post can retrieve a post of any post type so long as you know the post’s numeric ID, and get_term can retrieve a term from any taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies.. Because REST objects are segregated by post type-specific endpoints, however, there has not been a clear way to get a Post with ID 78 if you don’t know whether it is a page, post, or my-cpt.

The coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. /search endpoint now supports ?include and ?exclude parameters which take a list of IDs, and limit results to posts matching those IDs.

Examples:

  • To get post 78 when you don’t know its post type,
    • /wp/v2/search?include=78
  • To get posts 78 and 79 only if they are in the page post type,
    • /wp/v2/search?include=78,79&subtype=page
  • To search posts excluding post 78,
    • /wp/v2/search?exclude=78
  • To get term 87,
    • /wp/v2/search?type=term&include=78
  • To get term 87 only if it is a categoryCategory The 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging.,
    • /wp/v2/search?type=term&include=78&subtype=category
  • To search terms excluding terms 87 and 88,
    • /wp/v2/search?exclude=87,88

The search endpoint supports the _embed metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. parameter, so developers can therefore use the search endpoint to retrieve a full post or term response object in one request knowing only those object’s IDs.

As an example of how this could be used, imagine a custom blockBlock Block 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. which relates to a specific post. As of WordPress 6.1 developers can implement that block knowing only the related post’s ID, and could then create a hook to search for that post by ID and retrieve it using the Block Editor’s existing entity system:

/**
 * Dictionary of requested items: keep an in-memory list of the type (if known)
 * for each requested ID, to limit unnecessary API requests.
 */
const typeById = {};
​
/**
 * Query for a post entity resource without knowing its post type.
 *
 * @param {number} id Numeric ID of a post resource of unknown subtype.
 * @returns {object|undefined} The requested post object, if found and loaded.
 */
function usePostById( id ) {
    const type = typeById[ id ];
​
    useEffect( function() {
        if ( ! id || typeById[ id ] ) {
            return;
        }
​
        apiFetch( {
            path: `/wp/v2/search?type=post&include=${ id }&_fields=id,subtype`,
        } ).then( ( result ) => {
            if ( result.length ) {
                typeById[ id ] = result[0].subtype;
            }
        } );
    }, [ id ] );
​
    return useSelect( function( select ) {
        if ( ! id || ! type ) {
            return undefined;
        }
        return select( 'core' ).getEntityRecord( 'postType', type, id );
    }, [ id, type ] );
}

Pretty-printing REST endpoint JSONJSON JSON, 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. responses

WordPress 6.1 also introduces support for returning pre-formatted JSON from the REST API. #41998 lets developers request formatted JSON using a new _pretty query parameter or a filterFilter Filters 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., particularly useful when querying via curl or other tools which do not provide an option to format responses.

To format the JSON returned from a specific endpoint request, append the ?_pretty query parameter to the endpoint URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org.

To instruct WordPress to pretty-print all REST response bodies, a developer can use the rest_json_encode_options filter:

function myproject_pretty_print_rest_responses( $options ) {
        $options |= JSON_PRETTY_PRINT;
​
        return $options;
}
add_filter( 'rest_json_encode_options', 'myproject_pretty_print_rest_responses', 10 );

A developer or site owner may also disable pretty-printing globally using the same filter:

function myproject_disable_rest_pretty_printing( $options ) {
        $options &= ~JSON_PRETTY_PRINT;
​
        return $options;
}
add_filter( 'rest_json_encode_options', 'myproject_disable_rest_pretty_printing', 10 );

Filters are applied after, and can override, the _pretty query parameter.

Thanks to @spacedmonkey for peer review.

#core-restapi, #dev-notes, #dev-notes-6-1, #rest-api