Make WordPress Core

Opened 11 months ago

Last modified 5 weeks ago

#38900 assigned feature request

Customize: Add REST API endpoints for changesets

Reported by: westonruter Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Customize Keywords: needs-patch
Focuses: rest-api Cc:

Description (last modified by westonruter)

In WordPress 4.7, the customize_changeset post type was introduce to persistently store the customized state until the staged changes are published (see #30937). In 4.7 the changesets were managed using the same customzie_save Admin Ajax request that has always been used to send customizer changes to WordPress. However, changesets are designed so that they needn't be used in the current “Customizer” app at all. A customize_changeset post can be created by any means (such as via WP-CLI) and as long as the HTTP request includes the customize_changeset_uuid query parameter, the changes stored within the changeset will be applied to preview in the response. As such, changesets for headless sites and apps consuming the REST API to also make use of WordPress's framework for previewing changes.

In addition to an app being able to preview changes in read requests to the REST API, changesets must also be able to be written via the REST API. This is also relevant to creating new changesets for previewing changes on a site's frontend (frontend editing).

The Customize Snapshots has some initial read-only endpoints for the REST API: https://github.com/xwp/wp-customize-snapshots/pull/63
It did not yet implement support for writing changes: https://github.com/xwp/wp-customize-snapshots/issues/64

A few points about what how the changeset endpoints could behave:

  • Allow changesets posts to be created and updated, ensuring that content is in the proper format as an object mapping setting IDs to setting params. The content could be the decoded contents of the post_content.
  • Prevent editing of slug, since the UUID should never change.
  • Allow making changes to the content via PATCH method updates.
  • Use the UUID (post_name) of the customize_changeset posts as the resource IDs as opposed to the underlying post ID. We really don't need regular post IDs since snapshots have UUIDs. Really a random PUT request could be made to create a snapshot if it just supplies a proper UUID.
  • Let the endpoint be /changesets as opposed to /customize-changesets.

Ideally the customize_save Ajax requests initiated by wp.customize.previewer.save() and wp.customize.requestChangesetUpdate() could both make use of the changesets endpoints, replacing the use of the customize_save Admin Ajax request.

Updates to a changeset should be invoking WP_Customize_Manager::save_changeset_post() to apply the changes to the post.

Feature plugin repo: https://github.com/WP-API/wp-api-customize-endpoints

Change History (15)

#1 @westonruter
11 months ago

  • Focuses rest-api added
  • Owner set to valendesigns
  • Status changed from new to assigned

#2 @westonruter
11 months ago

Depends on #39103 to instantiate the WP_Customize_Manager without invoking the previewing of settings.

Update: Actually see #39221. But actually this may not matter because the /customize/changesets/:uuid endpoint wouldn't be itself requested with a customize_changeset_uuid param and so the customizer would't necessarily attempt to bootstrap itself and preview the changes.

Last edited 8 months ago by westonruter (previous) (diff)

This ticket was mentioned in Slack in #core-customize by westonruter. View the logs.

9 months ago

This ticket was mentioned in Slack in #core-customize by westonruter. View the logs.

9 months ago

This ticket was mentioned in Slack in #core by westonruter. View the logs.

8 months ago

#7 @westonruter
7 months ago

A customize-changeset REST resource would model the customize_changeset post type. Instead of a content field, it would instead have a settings field that is an object whose keys are the settings IDs and whose values are the setting params for the given settings in the changeset. Essentially, the settings would be the deserialized JSON contained within the changeset's post_content.

Also importantly a customize-changeset resource would include status, author, title, date, date_gmt.

The date and date_gmt would be readonly, unless the status is future.

I think that the /customize/changesets endpoint could potentially look like this.

  • GET /customize/changesets: List all changesets that the current user can read.
  • POST /customize/changesets: Create a new changeset, with a request body containing a valid changeset item resource.
  • PUT /customize/changesets/:uuid: Create or update a changeset with a given UUID, with a request body containing a valid changeset item resource. To publish a changeset, a status should be provided in the request. If a changeset is pre-existing and it already has a publish status, then the request should be rejected since published changesets are immutable (essentially revisions).
  • PATCH /customize/changesets/:uuid: Update a changeset with a given UUID, patching the provided settings with the values. This may not be needed, as we could also allow a PUT request that simply has null provided for the settings that are to be removed from the changeset.
  • DELETE /customize/changesets/:uuid: Deleting a changeset.

Note that as part of this, fine-grained capabilities should be introduced for the customize_changeset post caps, instead of mapping all to customize.

Essentially, the task here is to take the existing admin-ajax handler in WP_Customize_Manager::save() and convert it for REST. Once this is done, then the wp.customize.previewer.save() method and wp.customize.requestChangesetUpdate() functions in JS can be refactored to make use of the new endpoint. So perhaps the best approach would be to first start looking at the kinds of requests that these functions make, and then to flesh out what the endpoints are and what methods they allow. Then with that in place, tests can be written according to those requirements. And then the actual endpoints fan be written to satisfy the tests.

Last edited 7 months ago by westonruter (previous) (diff)

This ticket was mentioned in Slack in #core-restapi by westonruter. View the logs.

7 months ago

#9 @westonruter
7 months ago

  • Owner valendesigns deleted

#10 @westonruter
7 months ago

The plugin in the GitHub repo has been updated with a skeleton for the customize/changesets controller: https://github.com/WP-API/wp-api-customize-endpoints/blob/master/wp-includes/rest-api/endpoints/class-wp-rest-customize-changesets-controller.php

Also, stub tests for that controller have been added: https://github.com/WP-API/wp-api-customize-endpoints/blob/master/tests/test-customize-changesets-controller.php

Travis CI is set up. Readme has links off to Trac tickets.

@dlh is going to start digging in.

Last edited 7 months ago by westonruter (previous) (diff)

#11 @jbpaul17
5 months ago

  • Milestone changed from 4.8 to 4.8.1

While solid work has been made on this, it doesn't appear ready to land in 4.8 by this Friday so I'll punt and we'll look at landing in the next release. Keep up the great work!

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.

5 months ago

#13 @westonruter
4 months ago

  • Milestone changed from 4.8.1 to 4.9

#14 @westonruter
3 months ago

In 41205:

Customize: Introduce settings_previewed arg and getter on WP_Customize_Manager which controls whether WP_Customize_Setting::preview() should be called on settings.

The settings_previewed property eliminates the need for the Customizer components from having to look at global doing_ajax state. This is in particular needed when saving settings, as some settings will short-circuit the update operation if they detect no changes are introduced. This is also needed for low-level integrations with the Customizer, such as in REST API endpoints under development.

Props stubgo, westonruter, utkarshpatel for testing.
See #38900.
Fixes #39221.

#15 @westonruter
5 weeks ago

  • Milestone changed from 4.9 to Future Release

Work on this will continue in feature plugin and be tested during the development of a planned Customizer v2 feature plugin. No need to get this merged into core before feature plugin fully utilizes it in core.

Note: See TracTickets for help on using tickets.