Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REST API: Use posts endpoint for reusable blocks #10751

Merged
merged 7 commits into from
Oct 19, 2018
Merged

Conversation

aduth
Copy link
Member

@aduth aduth commented Oct 18, 2018

Related: #7453
Related: https://core.trac.wordpress.org/ticket/45098

This pull request seeks to refactor reusable blocks to avoid the need for (and thus enable removal of) the blocks API controller, in favor of the existing posts controller. Edit 2018-10-20: The controller class remains, solely for its custom check_read_permission implementation to avoid public visibility of published reusable blocks.

In implementing these changes, the custom controller was found to be used to:

  1. Return a limited subset of post endpoint properties (id, title, content)
  2. Flatten title and content fields (raw string used, no object of raw/rendered)
  3. Force delete on trash
  4. Force publish on save

My assessment of this is:

  • The first two points introduce a needless and unexpected inconsistency from the posts response
  • The last two points should be enforced at a post-type level if desirable
    • Are they desirable?
  • A subtlety of the second point is that now a user needs to have edit capabilities for the wp_block type to be able to view it in the editor, or to export the block. This is because the raw content (post.content.raw) is only included when the context=edit parameter is passed
    • This is perhaps a main deterrent to proceeding here, though is symptomatic of a larger issue around REST permissions where the prior implementation was an ad hoc workaround (effect of bumping permissions for otherwise unqualified users).

Post type supports title and editor were required to be added for the title and content fields to be included in the REST response [1] [2]. See also related discussion in #9964 (the changes here enable a Gutenberg editor for the Reusable Blocks management experience, thereby effectively closing #9964).

Open questions:

Should there be / how would there be a deprecation migration period for the controller removal?

Testing Instructions:

Verify no regressions in behavior of reusable blocks:

  • Creating / updating
  • Inserting
  • Managing all
  • Single block vs. template
  • Import / export

@aduth aduth added [Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) REST API Interaction Related to REST API labels Oct 18, 2018
Copy link
Member

@danielbachhuber danielbachhuber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Haven't tested but conceptually this is fine by me.

@slimmilkduds
Copy link

This wouldn’t by any chance fix (or be a step in fixing) the issue with preserving nested blocks when converting reusable blocks to regular blocks? (holding thumbs but is pretty sure it has nothing to do with that issue ☺️)

@aduth
Copy link
Member Author

aduth commented Oct 18, 2018

This is a refactoring change. It should have no impact (for better or worse) on existing UI behavior.

@noisysocks
Copy link
Member

Good thing I searched GitHub before working on literally this! 😛

There's no reason to have the custom endpoint. It stems from a time when it wasn't yet clear that reusable blocks would literally be mini Gutenberg posts that are embedded into a larger Gutenberg post.

Will review and test this now. Let's get it in for the API freeze.

Should there be / how would there be a deprecation migration period for the controller removal?

Not sure how we'd deprecate this without changing the URL, which isn't ideal.

Maybe we could add an error_log warning to 4.1 which informs developers that the endpoint will be changed in 4.2?

noisysocks
noisysocks previously approved these changes Oct 19, 2018
Copy link
Member

@noisysocks noisysocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works great! 👏

I left some suggestions for improvements—I'd really like if we kept the test_capabilities integration test so that it's hard to introduce a security regression down the line.

I suggest we wait for 4.2 to merge this and add a warning to 4.1 which logs that the route is changing.

*
* @dataProvider data_capabilities
*/
public function test_capabilities( $action, $role, $expected_status ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep this integration test. #3936 was a nasty bug which I don't want to regress, and it's a pain to manually test the CPT capabilities since one has to check every role/action combination.

See #4725 for context.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep this integration test.

Restored in e3b1279.

For what it's worth, it did prove to be a very useful test! I had found we in-fact need the controller for check_read_permission, because the default REST post controller otherwise ignores capabilities if the post is published.

https://github.com/WordPress/WordPress/blob/da7a80d67fea29c2badfc538bfc01c8a585f0cbe/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php#L1319

Discussed in Slack:

https://wordpress.slack.com/archives/C02RQC26G/p1539972633000100

'supports' => array(
'title',
'editor',
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the CPT now supports title and editor, we can go a step further and remove this line from gutenberg.php:267:

unset( $actions['edit'] );

This PR would then close #9964.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the CPT now supports title and editor, we can go a step further and remove this line from gutenberg.php:267:

Updated in c8ad73a

@noisysocks noisysocks dismissed their stale review October 19, 2018 06:24

Oops, spoke too soon!

Copy link
Member

@noisysocks noisysocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I spoke too soon! 😅

I'm noticing two small regressions:

  1. When exporting a reusable block as JSON, the saved file name is always json.json instead of e.g. my-reusable-block.json.
  2. Importing a reusable block from JSON always fails with Invalid Reusable Block JSON file.

screen shot 2018-10-19 at 17 24 15

@@ -184,7 +184,10 @@ export const deleteReusableBlocks = async ( action, store ) => {
] ) );

try {
await apiFetch( { path: `/wp/v2/${ postType.rest_base }/${ id }`, method: 'DELETE' } );
await apiFetch( {
path: `/wp/v2/${ postType.rest_base }/${ id }?force=true`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this some more, I think we should remove the ?force=true so that deleting a reusable block in Gutenberg matches what happens when you delete a reusable block in the Manage Reusable Blocks interface.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with this. As alluded to, seems like it would make sense to have this be controlled at the post-type level, for the sort of consistency you note. In the meantime, letting "Trashed" do its thing seems quite okay with me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to this one, we'll need to do similar with the forced "Published" status.

@@ -8,7 +8,7 @@
/**
* Tests for WP_REST_Blocks_Controller.
*/
class REST_Blocks_Controller_Test extends WP_Test_REST_Controller_Testcase {
class REST_Blocks_Controller_Test extends WP_UnitTestCase {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change might make someone somewhere upset, but implementing 9 abstract methods when the controller implements only check_read_permission is excessive, and would hint more at unreliability of tests for the extended posts controller.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implementing 9 abstract methods when the controller implements only check_read_permission is excessive, and would hint more at unreliability of tests for the extended posts controller.

Yeah, it's annoying. We can improve upon it at some point.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess another option could be extending WP_Test_REST_Posts_Controller, to inherit the tests implemented there we're assuming for our controller. Still lots of redundancy.

Or another way to signal "this is already tested elsewhere"? Extend WP_Test_REST_Controller_Testcase with the methods implemented as simple $this->skip with a message explaining?

(Not going to let this block merge)

@aduth
Copy link
Member Author

aduth commented Oct 19, 2018

I'm noticing two small regressions:

The two were in-fact the same, fixed in 0235f5d.

It reminded me also that since we pass context=edit, we need to check that the user would be able to edit the post before providing the export option: ac75c14

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@youknowriad youknowriad modified the milestones: 4.2, 4.1 - UI freeze Oct 19, 2018
@aduth aduth dismissed noisysocks’s stale review October 19, 2018 19:23

Feedback addressed. Separate technical review.

@aduth aduth merged commit 611fe31 into master Oct 19, 2018
@aduth aduth deleted the remove/blocks-controller branch October 19, 2018 19:23
@noisysocks
Copy link
Member

Thanks @aduth! Looks great.

antpb pushed a commit to antpb/gutenberg that referenced this pull request Oct 26, 2018
* REST API: Use posts endpoint for reusable blocks

* REST: Restore WP_REST_Blocks_Controller for permissions check

* Reusable Blocks: Enable post listing edit

* Reusable Blocks: Trash on delete action

* List Reusable Blocks: Provide context to post request

* Reusable Blocks: Verify edit capability on export action

* List Reusable Blocks: Import as published
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) REST API Interaction Related to REST API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants