WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.3k stars 4.11k forks source link

Proper server-side APIs for block modification #6494

Open braders opened 6 years ago

braders commented 6 years ago

I can see various PHP functions for parsing blocks out of the post_content (gutenberg_parse_blocks, do_blocks), but it appears not to be possible to modify these blocks server-side and insert an updated serialised content back into the database. There feels like a significant need for this, in order to support more complex use-cases.

Use Cases

  1. As a WordPress developer, I am often asked to migrate content out of legacy databases into WordPress. Usually, I migrate to ACF flexible-content and it is not unusual to be inserting several rows/ blocks of content. As block-based editors become more wide-spread it is likely that migrating between different block-based systems will become more common.

  2. In #5615 the question of how to update the markup for a block across all posts was raised. If a server-side API was available it would be able to loop through all posts and modify all instances of a single block. This could be a one-time migration script either run on plugin activation or via WP-CLI (depending on the context of the plugin and site).

  3. There is occasionally a need to allow post_content to be edited from the front-end by non-administrative users - For example, on certain types of membership sites. This is also supported by some form plugins. There is likely to be a desire to insert this content in a block-based fashion.

Ideal solution

I would love to see a proper object-based representation of the blocks, which would properly represent the inner-content, attributes and comments, with methods for updating and inserting blocks. It would be amazing if this object could be passed directly back to wp_update_post as the post_content arg, and serialised from there.

jasonbahl commented 6 years ago

Related to #2751

schlessera commented 6 years ago

I really like the idea of having a real object model of the blocks and making wp_update_post() understand this model, and would love to work on making that happen.

Blocks should be represented by the "Composite" pattern, to represent a tree that allows for easy traversal and modification, but can still be treated as a whole. So a call to the root object's render_html() would just recursively iterate over all its children's render_html() methods.

I'll work on creating a first PR to show how such an object model could work.

schlessera commented 6 years ago

I finished a first implementation that basically does the following:

$factory    = new WP_Block_Factory();
$post       = get_post( $post_id );
$block_tree = $factory->create_from_html( $post->post_content );

// $output will be equal to $post->post_content.
$output     = $block_tree->render_html();

The object tree is built up of composite objects and leaf objects.

image 2018-05-15 at 11 50 52 am

However, it seems that the data model that Gutenberg uses does not construct a tree out of composite objects and leaf objects (which is a standard pattern for such a use case), but rather adds an innerBlocks array to every single block (which is empty most of the times), turning every single block into both a leaf block and a composite block.

Is that the finalized data model design, or is this still up for discussion?

I can easily change the code to adapt to this data model instead, but I'd like to get confirmation first, as it seems this might have been a temporary work-around only.

rchipka commented 6 years ago

I implemented a concept for PHP block template partials, which are limited to updating or replacing the block string content.

Having access to the block model from within a template partial would be extremely powerful for server-side block rendering.

braders commented 6 years ago

@schlessera That looks like a good start, and fairly close to what I had in mind. I'm less familiar with the composite/ leaf concept, so I'm not sure how well this works with the Gutenberg data structure.

I can imagine a few more helper functions for inserting blocks might be useful (e.g. insert_at_position, replace_with) but your suggested approach seems to leave a solid base which can later be extended.

braders commented 6 years ago

@schlessera you mentioned you had an initial implementation working? In the absence of any feedback from the Gutenberg team I wonder if a pull-request would provide something to review in order to get this discussion moving again?

danielbachhuber commented 5 years ago

Related #11523

pablinos commented 5 years ago

@schlessera I'd love to learn more about your implementation here. As I understand it, the serialisation of most blocks is handled on the JS side. We're considering how to manipulate post_content containing blocks as it's being imported. At this point, things like IDs of images can change which need to be updated.

How is your render_html method implemented? Does it assume that all blocks have a server-side render function?

paaljoachim commented 3 years ago

Can we get a status update? I see there are various closed PRs and issues. Can we go ahead and also close this issue?

braders commented 3 years ago

I don't believe development ever got underway on this, although I would still love to see it happen. If there is an equivalent issue/ PR somewhere it would be great to post a link - I may have just missed it.