REST API Chat Summaries: Jan 31, Feb 7

This post summarizes the weekly REST API chat meetings on January 31, 2019 and February 7, 2019. (agenda/notes, Jan 31 Slack transcript, Feb 7 Slack transcript). Weekly REST API component office hours are held every Thursday at 18:00 UTC in the #core-restapi room in the Make WordPress Slack.

February 14 meeting agenda

Have a topic for discussion for today’s meeting on February 14 2019 18:00 UTC? Leave a suggested edit on the agenda document.

5.1: Dev Note needs?

  • The new rest_post_search_query filter could be called out in Other Changes.
  • changeset 44625 (update wp_die() to handle JSON contexts) could also be called out in Other Changes.

5.2 Tickets: Owners Needed

Gutenberg Widgets Endpoint

  • WordPress/gutenberg#13511: POC for a legacy widget block. @jorgefilipecosta requests input from REST API contributors.
    • Feedback provided around endpoint structure and parameter access
    • @kadamwhite proposes that user stories or use-cases for how these widgets will be consumed and displayed in the editor and rendered posts should be written for new endpoints, to inform implementation.

Authentication

  • All present agree we have a strong need for a core authentication solution. Existing plugins like the OAuth2 or JWT-Auth plugins work and are used on numerous sites, but need UX improvements and more documentation / example clients to be truly broadly applicable. OAuth2 in particular is seen as too complex / difficult to implement as a client developer.
  • Discussion on core auth since WCUS has centered on supporting basic authentication (only over SSL) (#42790), as the simplest path forward.
    • The main weakness of basic auth is that it ties all authorized applications to the user’s account name and password, so apps cannot be individually authorized or disconnected without creating new site accounts (not workable for e.g. the core mobile applications).
  • @koke thinks a JWT-based solution could be workable from the mobile applications.
  • The way CGI environments mutate authorization headers complicates any core-wide solution. A custom header may be necessary.
  • @espellcaste has volunteered to reach out to authors of existing plugin directory REST API auth solutions to get their input on what is best for core.

Upcoming Meetings

What can the REST API do for you? Join an upcoming meeting to help shape the future of this component!

#core-restapi, #meeting-notes, #rest-api

REST API Chat Summary: January 24, 2019

This post summarizes the weekly REST API chat meeting on January 24, 2019. (agenda/notes, Slack transcript). Weekly REST API component office hours are held every Thursday at 18:00 UTC in the #core-restapi room in the Make WordPress Slack.

Have a topic for discussion for the next meeting on January 31, 2019 18:00 UTC? Leave a suggested edit on next week’s agenda.

5.1 Tasks

  • One open Docs task: #45486 needs review (PHPDoc)
  • Awaiting Review ticket list needs triage & grooming but nothing currently stands out as a 5.1 priority

Tickets Awaiting Review

  • @desrosj to lead a bug scrub for this list next week, on Tuesday January 29, 18:00 UTC
  • As time permits prior to Tuesday, contributors may review that list and assign the Future Release milestone to any valid issues to show they have been triaged

5.2 Priorities

  • 6 tickets currently milestoned for 5.2. @desrosj proposes that every ticket assigned to a numbered release have an assigned owner.
  • Milestoned Tickets needing owner or review:
    • #41305 – Lazy String Evaluation: assigned to @timothybjacobs to investigate invalidating cache when locale changes within a request lifecycle
    • #39953 – Avoid updating date when modifying a “date floating” post (Related to #44975): needs owner
    • #44983 – Needs review
    • #45611 – Needs patch update to remove unused method

Gutenberg Priorities

  • content.rendered is not used by Gutenberg, and filtering the content for a large post slows down the editor load speed. @aduth suggests extending ?_fields= support to permit “deep” filtering, which the posts controller could then use to skip filtering post content where not needed, and raised the issue last week in the REST API component channel.
  • Delivering on this performance improvement within the block editor is architecturally complex, but implementing the nested _fields handling is tracked in #42094 and that ticket is now milestoned for 5.2 to lay the necessary groundwork.

Upcoming Meetings

What can the REST API do for you? Join an upcoming meeting to let the component team know!

#meeting-notes, #rest-api

REST API Meeting Agenda for January 24, 2019

The REST API team is taking inspiration from the JavaScript team and will be posting Agenda documents ahead of the meeting as Google Docs so that agenda items can be gathered from a wider and more diverse group.

All agenda items are welcome, from all teams and contributors; please post them as suggestions on this document.

This meeting will be at January 24, 2019 18:00UTC; note that this is one hour later than the last few weeks, after discussion with regular participants. As component maintainers we acknowledge there is no perfect time, but please leave a note below or feel free to contact us if this change negatively affects your ability or inclination to participate in the chat.

#agenda, #rest-api

New REST API Notice in 5.1

Edit: On January 14, 2019, the Good and Bad Practices section was added to show both correct and incorrect code examples.

Starting in WordPress 5.1, if register_rest_route() is not called on the rest_api_init action hook, a “doing it wrong” notice will be triggered. This notice is being added in an effort to encourage best practices when registering REST API endpoints.

First, let’s look at what happens when WordPress loads to set up the REST API and explore a few reasons why this pattern is beneficial.

REST API Bootstrap Process

WordPress does its best to ensure that the REST API is only loaded when a REST request is being performed. To do this, the rest_api_loaded() function is run on the parse_request action and checks for a value in the rest_route query argument. This argument is populated with a value when the Rewrite API matches a WordPress REST API URL. When a value is present, the rest_get_server() function is called to instantiate the WP_REST_Server class, store it for use across WordPress, and to run the rest_api_init action hook.

Performance

When register_rest_route() is called, it invokes rest_get_server() to retrieve the global WP_REST_Server instance created in the bootstrap process. But, if the instance has not been set up yet, it is instantiated then and the rest_api_init action hook is run. This means that every function added to the rest_api_init hook will fire at that time. This could result in a large performance hit.

For example, say register_rest_route() is called on the init action, or, just called in a theme’s functions.php file. The REST API server would be set up for every WordPress request, even those that are not actually aimed at the REST API.

Missing Endpoints

If register_rest_route() is called too early, it’s also possible that endpoints will go missing and never be registered. This happens when other plugins are not given the chance to register their rest_api_init hooks.

For example, say register_rest_route() is called directly in an mu-plugin file. This will cause the REST API to be set up before regular plugins are run, so their rest_api_init hooks will not be registered.

Good and Bad Practices

Let’s look at a few code examples and detail why they are good or bad.

Bad Practice

register_rest_route(
	'hello-world/v1',
	'/phrase',
	array(
		'method'   => 'GET',
		'callback' => 'myplugin_get_endpoint_phrase',
	)
);

In this example, register_rest_route() is called directly in a file without being attached to an action hook. This means the function will be called as soon as the file is loaded by WordPress. All of the potential issues detailed above are possible, and a _doing_it_wrong() notice will be triggered.

Good Practice

function myplugin_register_endpoints() {
	register_rest_route(
		'hello-world/v1',
		'/phrase',
		array(
			'method'   => 'GET',
			'callback' => 'myplugin_get_endpoint_phrase',
		)
	);
}
add_action( 'rest_api_ini', `myplugin_register_endpoints` );

In this example, register_rest_route() is correctly placed inside of a function that is added to the rest_api_init action hook. It will only execute when the rest_api_init action hook is executed. The potential issues detailed above are avoided, and no _doing_it_wrong() notice is triggered.

Changes Required

Plugins and Themes

All plugins and themes should double check that their REST API endpoints are being registered correctly using the rest_api_init action hook. This best practice is also mentioned in the Routes and Endpoints section of the REST API Handbook. If this was a resource used when developing, chances are you won’t have to change anything!

Unit Tests

Because some unit tests require custom endpoints to exist, it is not uncommon for a test method to call register_rest_route() directly. If a test method calls the function before rest_api_init, a previously passing test method may now fail. This can be fixed in two ways.

The first way is to use rest_get_server() to create the WP_Rest_Server instance for your tests. Since rest_api_init is run within that function, this will prevent the notice. This approach can be seen in the Tests_REST_Server class. The wp_rest_server_class filter still allows you to replace the default WP_Rest_Server class with your own for testing purposes with this method.

The second way is to call do_action( 'rest_api_init' ); directly in your test method or setUp() method. This method is for scenarios where complete control is needed over the REST server setup process. This can approach can be seen in the Tests_REST_API class.

You can read more information about this change in the ticket on Trac.

#5-1, #dev-notes, #rest-api

Gutenberg and the REST API, early May

Since I last wrote two weeks ago, we’re making progress! Key achievements for Gutenberg and the REST API include:

  • Support for who=authors was added to GET wp/v2/users, making it possible to accurately query for authors. WordPress, for better or for worse, defines an author as user_level!=0. See WordPress/gutenberg#6361 for the context on why we can’t add this logic client-side (#42202 for WordPress 4.9.6).
  • Improved performance for the _fields= query parameter (e.g. GET wp/v2/pages?_fields=id,title) by ensuring WordPress core will only process the fields requested for the response. Notably, this helps us avoid running the_content when we don’t need to be (#43874 for WordPress 4.9.7).
  • Minor enhancements to reflect existing WordPress behaviors:

The “Merge Proposal: REST API” GitHub milestone represents the distance we still need to close. Slowly, steadily, we’re bridging the gap, but we could use your help. Here are some of the issues we’re still working through:

  • To ensure all necessary data is available to Gutenberg, we’ve settled upon permitting unbounded per_page=-1 REST API requests for authorized users. This landed for GET wp/v2/users (WordPress/gutenberg#6627), is in-progress for GET wp/v2/(pages|blocks) (WordPress/gutenberg#6657), and needs to be addressed for categories, tags, and custom taxonomies. We also need to patch core with this enhancement (#43998 for WordPress 4.9.7?)
  • Capabilities can’t be processed directly client-side (WordPress/gutenberg#6361), so we’ve introduced a new targetSchema concept to communicate which actions a user can perform. See it in action with wp:action-sticky (WordPress/gutenberg#6529) and wp:action-assign-author (WordPress/gutenberg#6630). There are a few other actions we will need to work out, and then we’ll need to patch core (no ticket yet).
  • @adamsilverstein is putting together an improved autosaves implementation (WordPress/gutenberg#6257) that I literally cannot wait to see complete. I’m sure he could use some help testing in the near future.
  • @flixos90 is implementing a WP_REST_Search_Controller endpoint (WordPress/gutenberg#6489) to power the link search UI.

Join us tomorrow, Thursday, May 10 at 17:00 UTC in #core-restapi office hours if you’d like to chat through any questions you have.

#gutenberg, #rest-api

REST API Meeting Summary: May 3rd

This post summarizes the REST API component team meeting from May 3rd in #core-restapi (Slack archive).

Decisions around register_meta()

This meeting revolved around finding decisions on remaining questions regarding the approach for adding subtype support to register_meta(). Please read the announcement post for the meeting for background and context.

  • It was decided to go with the fourth approach outlined in the announcement post: Every registration of a meta key is accepted, regardless of whether the same meta key already exists on the same object type in another way. Meta keys registered for an object type and subtype will take precedence over meta keys only registered for an object type (i.e. less specific). This allows us to not having to deal with conflicts. Existing calls without using object types will continue to work – while they are now fallback, chances of a conflict are generally rather low in this way. Nonetheless, a major part of these improvements will involve precise documentation and education (more on that below).
  • Easy-to-understand wrapping functions will be introduced, such as register_post_meta(), unregister_post_meta(), and the same for terms, comments and users. In those functions, we can significantly help DUX: Instead of mentioning the very abstract term “object subtype”, we can here refer to it as the more common terms “post type”, “taxonomy”, etc. respectively.
  • New filters sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype} and auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype} will be introduced for metadata sanitization and metadata capability handling for specific subtypes. If one of these two filters is being used for the given variables, the existing sanitize_{$object_type}_meta_{$meta_key} and auth_{$object_type}_meta_{$meta_key} will not be executed – again, this is because metadata registration for an object type and subtype overrules metadata registration for only an object type.

An updated patch with the above changes is in place to test the current approach, available on the ticket #38323.

Documentation & Recommendations

The existing register_meta() function has not yet seen wide use in REST API-related plugins, so the transition to this new behavior should be smooth. However, should developers continue to omit object subtypes or fail to properly prefix their meta keys, over time the chance of conflicts between or within plugins will increase—therefore precise documentation and education are necessary to make all of this work in the long run.

To aid the transition to the new behavior, it will be recommended to switch existing calls to register_meta() over to include an object subtype. Additionally, we will no longer encourage direct calls to register_meta() when a wrapping function like register_post_meta() is available—this is in line with how it is currently preferable to call get_post_meta() over get_metadata( 'post' ), for example. We will also re-emphasize the importance of prefixing meta keys to ensure uniqueness.

Related Issues

Something that we will want to consider in the future is how to deal with meta keys of the same name that are registered for exactly the same object type and the same subtype. Currently, the second call would simply override the data registered by the first call. Alternatively, we could make the second call fail, keeping the first one the “winner”. However, this is a general problem in many areas in core (think about register_post_type() for example), so this may not be the appropriate point to discuss such a big topic.

May 10th Meeting Agenda

Next week’s meeting on Thursday, May 10th 17:00 UTC will continue to focus on discussing register_meta(), particularly review whether the current patch is a viable solution. We will also try to find an answer to the last, smaller question of the original announcement post, whether comment types should actually be considered subtypes in scope of metadata registration. If there is time left afterwards, we can also discuss the state of the current directly Gutenberg-related work in the REST API – otherwise this will happen the week after.

Please review the register_meta() ticket #38323 and the latest patch there, and chime in with your thoughts on the ticket or by attending the meeting!

#rest-api, #summary

Completing the implementation of metadata registration with the REST API

A priority of the REST API team for the upcoming 5.0 release is to finally enhance WordPress metadata registration so that it can cover common API use-cases. This will help with adaptation of the REST API by making management of custom metadata in existing content endpoints easier, which should in turn also benefit any metadata-related work in Gutenberg. This post provides some insight into the surrounding issues, shows the current progress of the improvements, and highlights what still needs to be discussed.

A little history on register_meta()

The register_meta() function has been around since 3.3, but did not attract much attention with developers until WordPress 4.6 introduced enhancements to permit metadata registration for use within the REST API. As with other metadata functions, an object type (by core definitions either a “post”, “term”, “comment”, or “user”) needs to be passed to the function, alongside the meta key to register and the arguments for its behavior.

However, metadata in WordPress is often used only for a subset of one of the above four types. When dealing with post meta in a plugin for example, that post metadata commonly only applies to one or more specific post types – not to all posts of any post type. That is what currently makes register_meta( $object_type, $meta_key, $args ) unusable for the majority of REST API-related cases. Before the enhanced version was introduced in 4.6 many thoughts were put into this concern, with a subtype-aware implementation even being merged into core. That implementation was reverted before the release because it was unclear how to handle conflicts (more on that below). The ticket where all those changes were discussed is #35658.

Misconceptions about register_meta()

The improvements and their documentation caused developers to listen up, but unfortunately since the concept of an object type is rarely exposed in high-level WordPress APIs, many people misunderstood the first parameter as requiring a post type because post meta is the most common kind of metadata used by plugin developers. Some developers started using the function to register post type-specific meta keys without that function actually supporting that, as shown in this example:

Note:

This does not do what you may think it does:

register_meta( 'book', 'isbn', array( ... ) );

The code above will not register an ISBN number meta key for a “book” post type. It will register that key for a custom object type “book”—which probably doesn’t exist, unless a whole custom meta database table, a custom object database table, and surrounding setup has been implemented.

Those function calls fortunately don’t cause any harm in most cases since WordPress only contains four object types that use metadata (ignoring multisite). It becomes problematic though if the function is used to register metadata for the “post” post type.

Note:

This also does not do what you may think it does:

register_meta( 'post', 'some_meta_key', array( ... ) );

Since the “postpost type shares a name with the “postobject type, and since, again, the first parameter of register_meta() is for object type and not for a post type, register_meta() will register that meta key and arguments passed for all posts of any subtype (post type).

If you’re reading this and have used register_meta() in a way where you assumed it could register metadata for a single post type or taxonomy, at present we recommend you switch to using register_rest_field(), which is currently the only (however a little more involved) way to achieve this.

Adding subtype support for metadata behavior

A follow-up ticket #38323 aims to finally implement this missing functionality to register_meta() so that there’s an easy-to-use API to handle subtype-specific metadata in the REST API. It picks up the approach used before, where an additional object_subtype argument in the $args parameter can be used to specify the subtype the meta key should be registered with. Picking up the aforementioned example, you could register the ISBN for a “book” post type via the following code:

register_meta( 'post', 'isbn', array(
	'object_subtype' => 'book',
	...
) );

Open questions regarding subtype handling

Implementing meta registration for subtypes and modifying existing behavior to account for it is rather straightforward, and there is a patch available to experiment with the current approach. There are a couple things that need to be discussed though:

  • How should we deal with or prevent conflicts between meta keys of the same name and object type? The method currently allows to register metadata for an entire object type of course, so we cannot simply change that now and prevent those calls entirely. It appears we have four alternatives here:
    1. Allow meta keys of the same name and object type to be registered in any way. In case a meta key is registered for the current subtype, but also more generally for the object type, the behavior registered for the subtype takes precedence. Meta keys are internally stored nested under their object type and object subtype ($wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]). This is how the current patch on the ticket works, mainly because it is the most straightforward and flexible approach (it was also how the original code from #35658 worked). However it doesn’t deal with conflicts at all, so it is likely not preferable. An issue would be that on every update of a value, sanitization would happen for both behaviors, easily resulting in invalid data and unexpected errors. Throwing notices would be an option – but it would only help preventing conflicts, not actually prevent them.
    2. Allow meta keys of the same name and object type to be registered either per subtype OR for the entire object type. It would be based on whoever comes first takes priority. Meta keys are internally stored nested under their object type and object subtype ($wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]). If someone registers a meta key for an object type after someone else already registered the same meta key for a subtype of that object type, the process should be rejected and fail. If someone registers a meta key for an entire object type without the same meta key already being registered for a subtype of that object type, afterwards all meta keys for a subtype of that object type would be rejected. This prevents all possible conflicts since meta keys will only exist once per object type/object subtype combination, but still provides the flexibility of having multiple meta keys of the same name for different object subtypes. The implementation to prevent the conflicts during meta registration would be a little more involved though.
    3. Allow meta keys of the same name and object type to be registered only once in total. It would be based on whoever comes first takes priority. Meta keys are internally stored nested under their object type only, without an additional level for their object subtype ($wp_meta_keys[ $object_type ][ $meta_key ]). Whoever comes first, can register their meta key, every following request to add the same meta key for the same object type afterwards will be rejected. This prevents all possible conflicts since the data structure alone makes it impossible for two meta keys of the same name and object type to be registered. The approach generally appears to not be flexible enough: For example if two different post types were using a meta key of the same name, they wouldn’t be able to co-exist. However, based on the assumption that developers prefix all their metadata (which is probably not taught often enough), this option could very well work and be a straightforward solution.
    4. Allow meta keys of the same name and object type to be registered in any way, but use the behavior registered for the entire object type as a fallback only. In other words, if the same meta key exists with a subtype, only run that logic – for all subtypes where there is no specific behavior available, fall back to the behavior registered on the entire object type. To be precise, the difference between this approach and the first one is that in the first one the behavior (like sanitization and auth) would be executed for both, while here it only happens for the object subtype or the object type when no subtype-specific handling is registered. This is a conflict-free approach that at the same time doesn’t require any restrictions where calls to register_meta() would need to be rejected. The idea of using meta keys registered for an entire object type as fallback is slightly different from the other variants, but it seems to work well. It should still be highlighted that meta keys should be prefixed, but if that is a given, this implementation would even allow an individual plugin to provide more flexible logic for its metadata that may be needed for all post types (general behavior as fallback, subtype-specific behavior where needed).
  • Should we introduce easy-to-use wrapper functions like register_post_meta( $post_type, $meta_key, $args ) and register_term_meta( $taxonomy, $meta_key, $args ) which wrap register_meta() appropriately? The reason those might be useful is that the concept of object types and object subtypes is not commonly exposed in core’s documentation & high-level APIs (think about *_post_meta(), *_term_meta(), *_comment_meta() and *_user_meta() all wrapping the respective lower-level *_metadata() function). By adding these methods we would then recommend to only use those, and never recommend the use of register_meta() itself (as registering metadata for an entire object type is probably not desired). The only downside would be that comments and users don’t really have subtypes, so those two functions would either have a redundant first parameter or not have that parameter at all (which wouldn’t be future-proof).
  • A more specific issue: Should a comment’s comment_type value be considered a subtype? While one could argue that they are subtypes, they are treated entirely differently and do not really define how that comment works or how it can be edited. There’s also no flexible API around it to register additional comment types, and in the REST API there are no individual controllers per comment type. Currently, the patch ignores comment types, but this is still open for discussion.

Upcoming Meeting

The above items will be discussed in next week’s upcoming REST API meeting which will take place at the regular meeting time, Thursday, May 3rd, 2018 at 17:00 UTC in the #core-restapi channel. If you’re interested, please attend this meeting so that we can move forward with this ticket, as it should be included in WordPress 5.0. Also feel free to review the latest patch on #38323 and leave a comment on the ticket. While it is unlikely that this is the final implementation, a lot of it would not need to be adjusted regardless of the outcome for the above questions.

Extra credit goes to @kadamwhite for proofreading and several improvements.

#agenda, #rest-api, #team-update

Gutenberg, REST API, and you

Fancy yourself some challenging architectural puzzles? Have we got the ticket for you!

As you may know, Gutenberg uses the WordPress REST API as a bridge between the land of JavaScript and land of PHP. There were a whole host of conceptual challenges in translating WordPress internals to REST — and even more we still haven’t solved!

We’d love your help 🙂 Read through and comment on the issues linked below as you have time. Then, if you’re available, join the next REST API office hours for a rousing conversation: Thursday, April 26 at 17:00 UTC

Even more curious? Dive into the entire Gutenberg REST API milestone and all Trac tickets tagged ‘rest-api’.

Thanks!

#gutenberg, #rest-api

Improvements in REST API request parameter regular expressions

With WordPress 4.9, a bug has been fixed which would cause unexpected numeric results to be included in the parsed URL parameters for a REST API request. Prior to this change, calling WP_REST_Request::get_params() for a request like /wp/v2/users/(?P<id>[\d]+) with an ID of 10 would return array( 'id' => 10, 1 => '10' ), where the latter numeric key is unnecessary and a result of PCRE matching against a named subpattern (see preg_match() documentation). The fix ensures that the above request now only returns array( 'id' => 10 ) instead. This helps for example to verify that a request does not include more than a few specific parameters.

The WP REST API docs have always been using named URL parameters, using regular (numeric) matches was never recommended. With this bug fix in place, using named parameters is now effectively required, for example /my-namespace/my-endpoint/(?P<numeric_param>[\d]+) must be used instead of /my-namespace/my-endpoint/(\d+). For background discussion on these changes, see #40704.

#4-9, #dev-notes, #rest-api

REST API Roadmap

If you’ve been following WordPress development this year, you may be wondering “what’s been happening with the REST API focus?” We’ve been a little under-the-radar for most of the year so far, so we thought publishing an update and roadmap might be a good idea.

For new contributors looking to get involved with the REST API focus or WordPress generally, there’s never been a better time, and we’d love to have your help on our projects. Read on to see what we’ve been doing, where we’re going, and how you can get involved.

Since 4.7

Since the REST API was merged into core in WordPress 4.7, development activity has unfortunately been light. The merge into core was a huge effort, and after shipping in 4.7 we saw a drop-off in contribution and overall momentum as many API contributors took a break to recover from the stress of the merge. These contributions have not returned to previous levels, and there’s a few factors behind this: the move to Trac, lack of a forward roadmap, and overall fatigue have hampered our ability to move forward quickly.

The core REST API focus goal is to utilise the REST API within the WordPress admin. Defining the scope of this project has involved auditing all admin-ajax calls, as well as the filters used inside these calls, and where they are used. In addition, we’ve been working on the low-level JavaScript utilities we need to offer conceptual compatibility: while we can deprecate and remove old PHP filters, we need to offer new JS-based filters to replace them.

The admin-ajax audit revealed that the majority of ajax requests can be grouped into four categories: Media, Themes, the Editor, and List Tables. The code for both Media and the Editor will gradually switch to the REST API moving forward with development around Gutenberg, and likewise endpoints for better managing Themes are expected to be incorporated into Customizer work.

Rather than simply refactor the existing code for the other actions in a piecemeal fashion, we’ve been working on prototyping bigger groups of related changes and features, starting with the New List Tables and Live Settings.

A significant portion of existing admin-ajax code is for handling list table actions. The existing JS code for these actions is particularly difficult to work with, and the existing list table actions user experience is frustratingly inconsistent (for example, deleting a comment happens inline, whereas deleting a post causes a page refresh). A reworking of the code has the potential to improve UX significantly. New List Tables allows us to explore ideas around how we can improve the content organisation and management experience in the admin. This is a prototyping plugin where we’ve been exploring backwards compatibility techniques, and thinking about how a theoretical new management interface would look.

The Live Settings prototype uses the REST API settings endpoints to add live saving to the Settings screens. This dovetails with the work underway by the Accessibility team to switch to the Settings API, and the two projects will be able to work together in the future.

In addition to these API team projects, work has continued on REST API-related pieces on other teams, notably the Customizer and Multisite teams, who are working on API endpoints in their respective components.

Renewing our focus

Moving forward with the REST API, there’s a few key items we’re going to be focussing on. These items will have their own dedicated subteams and development cycles, and will work in parallel. The two broad goals are to use the API in the admin, and to solve authentication for external applications.

API in the Admin

Getting the API used in the WordPress admin is our primary focus. While it is technically possible to directly switch from admin-ajax calls to REST API calls, this is essentially refactoring with no real user benefit. Instead, we want to focus on changes that can improve the user experience.

For the feature prototypes (New List Tables, and Live Settings), we’re engaging members of the Design team to lead these features from a UX perspective. So far, these prototypes have been primarily about proving out the features and ensuring it’s actually technically possible to migrate these features to use the REST API; with the initial success on the technical side, we need to switch focus to delivering compelling user experiences.

New List Tables will be working with the goal of prototyping improved content management, using the REST API. This includes unifying and standardising existing interactions, and improving the perceived performance. This is a React-based prototype, and uses the existing REST API endpoints.

Live Settings will be working with the goal of making settings changes seamless. We’ve seen huge strides forward with the Customizer for updating your site, and the backend settings deserve a better experience to match. Live Settings touches on similar areas as the Settings API Enhanced project spearheaded by the Accessibility team; we plan to continue working independently to avoid blocking each other, while keeping in touch about the respective projects.

Work on converting existing admin-ajax code to use the REST API will continue, however this won’t be a priority, as it generally doesn’t provide a strong benefit to end users. Most admin-ajax actions will naturally be deprecated as part of progress by other focuses, including Gutenberg and plans around the Media Library. We’ll continue working with other teams and focuses on their efforts here.

Authentication

External authentication is an unsolved problem, and one that’s crucial to API use outside of WordPress core itself, including the official WordPress apps.

There are two key problems to solve here: how do apps act on behalf of a user (authentication), and how do sites recognise valid apps (initial connection). We have existing solutions to both these problems (OAuth 1.0a and the Broker system respectively), however these are not the easiest solutions, and aren’t adequate for all use cases.

To date the most complete authentication solution maintained by the REST API team has been a plugin providing OAuth 1.0a authentication. Moving forward, we are switching authentication focus to OAuth 2. As Matt announced last year, we are going to begin shipping HTTPS-only features in WordPress: this allows us to switch to OAuth 2. Work started during the WordCamp Europe contributor day on a new official OAuth 2 provider plugin which is now under ongoing development.

Simplifying the initial connection is a much harder piece, and this is a long-term project. Eventually, this should be as simple as a “Connect to WordPress” button, requiring minimal effort for app developers and no effort for users. This is a complex problem to solve, and no similar software has to work on the same scale we have. In the meantime however, we’re going to investigate pre-configuring Core to recognize and permit authentication from certain default apps, including the official WordPress mobile applications. Whitelisting applications in core is a practical expedient but this solution is not sustainable in the long-term, and should be replaced with a better system as soon as feasible. Work on solving this issue will be in the mid-term, however, as we need to ensure we have solid basics first.

Help Us!

The toughest challenge facing the REST API team right now is resourcing. There are only a few people working on the API regularly, and we need help to build out our projects—which is hopefully where you come in. We need people of all skillsets to help on New List Tables, Live Settings, and OAuth 2. This includes regular contributors, JS developers, and designers. And all of this will need documentation, too: following a productive contributor day at WordCamp Europe we are making progress expanding and reorganizing the REST API developer handbook, and would gladly welcome any interested docs contributors.

Our plan is to release the first public beta of each of these projects within the next month, with regular releases from each project following that. New List Tables and Live Settings could be part of either a 4.9 or 5.0 release, while OAuth 2 will remain as a plugin until fully proven out, and would likely target a core release next year. This also requires coordination with the Mobile team, and finalising the approach to usage inside the apps.

If you’re interested in getting involved, we’d love to get your help. The API holds weekly meetings every Wednesday at 13:00 UTC (next meeting at Wednesday at 13:00 UTC), and we’re always happy to spend time helping people get started contributing.

#rest-api, #roadmap