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

Standardise data access for blocks on the server #58510

Closed
draganescu opened this issue Jan 31, 2024 · 3 comments
Closed

Standardise data access for blocks on the server #58510

draganescu opened this issue Jan 31, 2024 · 3 comments
Labels
[Feature] Block bindings [Feature] Block hooks Needs Decision Needs a decision to be actionable or relevant [Type] Enhancement A suggestion for improvement.

Comments

@draganescu
Copy link
Contributor

draganescu commented Jan 31, 2024

This is a bit late in the game but I wanted to start this discussion better late than never:

Problem: on the server there are many ways to retrieve the data you need for a block. This leads to various code spaghetti in block rendering callbacks which then later hamper block API advancements.


Case in point: server side previews and pattern overrides are both stuck at showing placeholders for empty image blocks. Another block, the cover block, decides in its rendering function that a cover block displaying a featured image means it has an empty URL. Pretty arbitrary. The same goes for the featured image block which is a post showing an image but has no URL attribute defined.

Case in point: block hooks need to add feature specific code to block rendering callbacks to hook into the data these blocks fetch from their associated entities. The way to retrieve data if the block has controlled inner blocks is a free for all.


Solution:

use the incoming power features of
block hooks and block bindings
to solve this problem.

''How?'' By nudging block developers - including core contributors - to use standard methods to access required data:

  • make block bindings only update attribute values from sources and leave the rendering to the block rendering callback. That means let’s not do https://github.com/WordPress/wordpress-develop/pull/5888/files#diff-c569b1ecb11a007a563788a481710b51e0cb21cd1d1885490bf9c91777842f23R297 this part and instead offer a helper function for replacing markup in static blocks from HTML sourced attributes.

  • If a block does not use exclusively attributes to represent the data they render they’ll have problems with binding, because the binding will not happen as a last action indifferent of the render callback’s soup.

  • make block hooks filter a function like get_controlled_inner_blocks which the block render callback uses to get data associated with it (like the navigation block gets its navigation from a wp_navigation post). Instead of PRs like Update Navigation block to render hooked inner blocks #57754 (comment) this one add a singe server side way to retrieve data from entities that hold controlled inner blocks and filter that. (cc @ockham for awarenes.)

  • If a block does not get its controlled inner blocks via this function, block hooks won’t work.

Trade Offs:

  • block hooks and block bindings lose some of their auto-magic awesomeness.
  • authors will have to opt in via updating their blocks to fit the paradigm described above.

Wins:

  • Data flow direction is always predictable - if I filter attributes before rendering the effect will be visible in the render.
  • Extension is more predictable - associations between blocks and their entities are expressed in code via using one extensible method of data retrieval.
@michalczaplinski
Copy link
Contributor

Hi @draganescu! 👋 Thanks for opening this discussion!

I must say that I'm not quite following here what the specific problem is. Could you articulate it in a different way with some examples?

server side previews and pattern overrides are both stuck at showing placeholders for empty image blocks.

I don't understand what you mean here. What should an empty image block render other than a placeholder?

If a block does not use exclusively attributes to represent the data they render they’ll have problems with binding, because the binding will not happen as a last action indifferent of the render callback’s soup.

I've read it a few times but I still don't understand 🙁 . What do you mean by "last action indifferent of the render callback’s soup"?

make block bindings only update attribute values from sources and leave the rendering to the block rendering callback. That means let’s not do https://github.com/WordPress/wordpress-develop/pull/5888/files#diff-c569b1ecb11a007a563788a481710b51e0cb21cd1d1885490bf9c91777842f23R297 this part and instead offer a helper function for replacing markup in static blocks from HTML sourced attributes.

Please correct me if I misunderstood. You're suggesting removing the replace_html() function from its current place and leaving the responsibility of rendering a blocks with updated attribute values (the values coming from a block binding source) to that block itself. Specifically, the block would have to use some helper to update the static block's HTML.

The problem I see with this approach is that whenever a value coming from a source changes, the value in the static block would not be updated automatically. The user would have to e.g. re-save the post. How do you think this could be overcome?

@draganescu draganescu changed the title Standardizing data access for blocks on the server Standardise data access for blocks on the server Mar 5, 2024
@gziolo
Copy link
Member

gziolo commented Oct 2, 2024

To clarify the current status, Block Bindings are around since WordPress 6.5. For the time being, the mechanism for replacing attribute values works with 4 core blocks: Paragraph, Heading, Image, Button. In the near future it’s going to be open for dynamic custom blocks and then eventually for everything else. The way it works is as follows during block rendering:

  • If an attribute is connected to a source then the value of the attribute gets set to what the registered source computes.
  • The saved HTML gets processed to replace the parts for computed block attributes.
  • When render_callback is defined the gets called with updated attributes and updated saved HTML giving a chance the developer to do further operations.

I believe it’s offering enough flexibility to cover some of the use cases provided. @draganescu, is there anything you envisioned differently? What are the criteria to consider this issue finished?

@gziolo gziolo added the Needs Decision Needs a decision to be actionable or relevant label Oct 2, 2024
@draganescu
Copy link
Contributor Author

I think the way you described the flow @gziolo is fine in terms of extensibilty. The fact that bindings are called, attributes updated and html processed before render, is great. It offers last minute options to process at render time specific situations.

My intent here was to use the block hooks feature to nudge a standard way to work with data on the server in two situations:

  • dynamic blocks rendering data which is not in attributes
  • dynamic blocks rendering inner blcoks found in entities

My idea was that if the new binding/hook architecture would work in such a way that only calling certain functions executes the bindings then people will start using the standard ways of accessing data. I think it wasn't great idea but the problem still remains:

there is little control over the connection between data in attributes and the final render callback, thus exposing us to the same situtation where filtering attributes has no effect on rendered output because the render callback gets data "directly" not from attributes.

I do think this issue can be closed. The hooks/bindings API is around for quite a while and this issue is not fundamental to the feature - it mentioned it as a sort of devex opportunity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block bindings [Feature] Block hooks Needs Decision Needs a decision to be actionable or relevant [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

No branches or pull requests

3 participants