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

Synced Patterns iteration for WordPress 6.7 (Draft) #62566

Open
11 tasks
talldan opened this issue Jun 14, 2024 · 11 comments
Open
11 tasks

Synced Patterns iteration for WordPress 6.7 (Draft) #62566

talldan opened this issue Jun 14, 2024 · 11 comments
Labels
[Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) [Type] Iteration Scoped iteration of an effort from a tracking issue or overview issue ideally for a major release.

Comments

@talldan
Copy link
Contributor

talldan commented Jun 14, 2024

Succeeds #59819.

This is currently a draft and needs discussion/refinement

Improved customization flows for synced patterns / Theme bundling of synced patterns

The following issues solve a number of related aims:

  1. Themes can include synced patterns, allowing them to take advantage of pattern overrides
  2. Users can customize theme provided patterns using the same approach as template parts (Customize / Clear Customizations)
  3. Brings more parity between template parts and patterns for a potential future unification (template parts become patterns)

Related issues

Patterns as sections

Connects with the work on section styling and zoomed out editing.

Pattern overrides / Block bindings

Continuation of block bindings and pattern overrides.

TODO: Track anything punted from the 6.6 Beta/RC period. There may also be further UI improvements to pattern overrides to define.

Extensibility

Code Quality

@talldan talldan added [Feature] Synced Patterns Related to synced patterns (formerly reusable blocks) [Type] Iteration Scoped iteration of an effort from a tracking issue or overview issue ideally for a major release. labels Jun 14, 2024
@andrewserong
Copy link
Contributor

Thanks for putting all this together! I'm sure many of these features will be complex to implement (and many are quite related), but from my perspective the standout here for me would be #59272 (Add support for synced theme patterns (with overrides), as it sounds like that would really make the feature impactful for theme developers, or agencies that build a theme that'll be used across a number of clients.

@justintadlock
Copy link
Contributor

Just adding a 👍 from me. My goal is to sync every pattern in my theme so that I can keep the design updated on a user's site without them having to reimplement the updated patterns in their posts, pages, and customized templates.

@ndiego
Copy link
Member

ndiego commented Jun 18, 2024

Themes can include synced patterns, allowing them to take advantage of pattern overrides

I just finished an article on the WordPress Developer Blog covering the introduction of pattern overrides. This enhancement is amazing, but it has limited applications for agency developers due to the current limitations of synced patterns.

In the post, I use the example of a Card layout. Here's a screenshot of the finished product with overrides.

override-synced-pattern-preview

While this was created in the Editor, which is great for many types of WordPress users, folks building sites for clients would often like to keep this design in a pattern file provided by the theme. This would allow them to keep the file in version control and serve any future updates to the design through the pattern file instead of having to manually update the synced pattern stored in the database.

Allowed themes to include synced patterns would be a massive win for this user base and dramatically increase the power of patterns and block themes.

@fabiankaegy
Copy link
Member

I can only second what @ndiego shared above.

Besides the ability to have synced patterns in themes however there is one additional thing that would make this even more powerful. And that is the ability to add custom block overrides in custom blocks.

For example in a custom icon block I want to be able to allow folks to override the icon used. Is that something that can get tracked here or should it get tracked with GbR block bindings feature?

@dballari
Copy link

dballari commented Jun 19, 2024

I just finished an article on the WordPress Developer Blog covering the introduction of pattern overrides.

Nice post @ndiego, thanks a lot. It will sure be an awesome enhancement.

Allowed themes to include synced patterns would be a massive win for this user base and dramatically increase the power of patterns and block themes.

Doing this is not that difficult if we try to do it the easy and direct way: save them in xml format instead of saving theme as files in the patterns subfolder, and import them in the WordPress installation using the wp import / export tool.

There are two problems here:

  1. For the moment, xml files are not allowed in themes, I do not know why, but they are allowed in plugins (look at the woocommerce v9.0.0 sample-data folder). I believe this could easily be solved: Just like in plugins.

  2. People may thing the import / export tool looses referential integrity. That is, if I have some content that includes a synced pattern in one database (markup: <!-- wp:block {"ref":XYZ), where XYX is the id of the synced pattern) then I would loose it if I export and import to a new database. But this is not true, the import / export tool tries to keep the id every time it’s possible. And just in case and id of a synced pattern changes, we could perform a search replace action on the database, just like what I’m doing in a plugin of mine. Look at lines from 389 to 545 of this file

So with solution to this two problems, there is nothing that would keep us from including synced patterns in themes. Just in the synced-patterns subfolder in xml format or in the assets/xml subfolder.

@ndiego
Copy link
Member

ndiego commented Jun 19, 2024

Doing this is not that difficult if we try to do it the easy and direct way: save them in xml format instead of saving theme as files in the patterns subfolder, and import them in the WordPress installation using the wp import / export tool.

This is an interesting approach, but I strongly suggest that synced patterns operate the same way unsynced patterns do in theme folders. They should be basically identical except for a few block attributes. While this approach may be more complicated to architect, the end result would be a simpler theme development experience.

@dballari
Copy link

This is an interesting approach, but I strongly suggest that synced patterns operate the same way unsynced patterns do in theme folders.

Yes, you are probably right.
The only detail is that, one thing is the definition of a pattern, which is best as a html file in the patterns subfolder.
The other thing is that, by definition, a synced pattern only becomes synced when created by the user, from the editor and is always in the database. In the html pattern file you can’t specify if that will be the case of not.
That's why I just thought of suggesting a different way to define something which has to become synced (that is, which is meant to finally live in the database, not in the theme folder).
But, of course, maybe I'm understanding things in a little different way.

@youknowriad
Copy link
Contributor

youknowriad commented Jun 20, 2024

I've been thinking about this issue and the different use-cases mentioned here (also in relation to the unification of patterns and template parts) with the goal about simplifying the concepts in the process and unifying everything. I believe the more we consolidate, the better is for theme and plugin authors to understand what's possible and for users to understand how to use the features.

So with this in mind, here's a proposal:

  • A pattern is always a pattern and works the same regardless of where it comes from (where it's defined).
  • A pattern can be either registered using a PHP API (already exists)
  • A pattern can be registered using a theme file in patterns/pattern.php (or html but that's a discussion for later). (already exists)
  • A pattern can be "registered" directly in the database (created by the user) (already exists)
  • A pattern can be synced or unsynced regardless of where it comes from. (Only user created patterns can be synced today)
  • A pattern is referenced by a "slug" in most case (template part slug, pattern slug, or a random slug when created by the user). The slug is universal and is the identifier in the PatternRegistry, which means it works for all of the registration methods of (php api, file, user DB, template part file)
  • A pattern can also be referenced by an "id" (legacy maybe deprecated in the future but a question for later)
  • A pattern regardless of where it comes from can be modified in the UI.
  • Permissions: some patterns might have other metadata to indicate different permissions (Maybe theme created patterns are automatically stricter and things like that)

What needs to be done to achieve this?

An iterative process is needed in order to achieve the above without breaking change while offering a migration path to this "consolidated" pattern-based approach.

  1. First we need to allow the core/block block to reference a pattern using a "ref" instead of an "id". One decision that need to be made here is whether we should use the template part approach (wrapper for both frontend and editor) or the reusable block approach (wrapper only for the editor). I'm definitely for the template part approach for its simplicity and consistency in terms of styling (no hacks to make it work).
  2. Doing 1 means we can add a flag to the PHP API to register patterns (and the file API) to define whether a pattern should be treated as synced or unsynced by default.
  3. There's probably some work to be done on the REST API, to be able to fetch the patterns using the same REST API regardless of where they come from. Rather than using the default CPT REST API that only retrieves user saved patterns, an approach similar to the templates and template parts API is probably needed (smart IDs, merging of patterns from different sources probably using the pattern registry class). This item might need to be addressed first depending on whether it's a blocker or not.
  4. Legacy handling of template parts (can be registered as patterns from now one, they just have special slugs maybe)
  5. Unify site editor UI.
  6. Consider whether to soft-deprecate the pattern block reference a pattern using an ID.

Aside I created a very similar proposal for style variations and I believe that if we do things properly, the three concepts (patterns, style variations and templates) will end up behaving exactly the same way:

  • 1 file = 1 entity = 1 entry in the database (or 0).
  • Each entity has a PHP API to register it from plugins... without files or DB entries.
  • Each entity can be edited in the UI and behaves the same regardless of how it was registered.
@talldan
Copy link
Contributor Author

talldan commented Jun 21, 2024

There's probably some work to be done on the REST API, to be able to fetch the patterns using the same REST API regardless of where they come from.

This is something that will be important to get right. If the plan is to unify patterns/template parts in the future, then it'll make sense for this endpoint to return template parts, but it'll be challenging to have it work that way from the start until all the smaller details are solved (areas, origins, sources etc.). Perhaps developing an experimental endpoint in the plugin first is the way to go.

I mentioned in a comment that it might be good to try and help migrate the navigation block to use slugs first, and hopefully learn from that what the right solution is for patterns - #55911 (comment).

@youknowriad
Copy link
Contributor

On the endpoint, I agree it's important to get right.

I was thinking that we can probably explore "just" copying what we already do for template and template parts's endpoint and just use the "patterns registry" as the "source". The DataViews page in the site editor for "patterns" mix and matches between using the template part REST API and patterns which seems like an opportunity to try and test (unify) that endpoint.

@roygbyte
Copy link
Contributor

roygbyte commented Jul 9, 2024

It is possible to use a manually marked up core/block tag and the render_block filter to dynamically insert a database-stored pattern into a theme's template, template part, or pattern file.

Imagine this is an excerpt from templates/home.html:

<!-- wp:block {"postName": "product-card"} /-->

The filter below will extract the postName attribute and query the wp_block post type for a matching post name (i.e.: slug). It will then replace the given block's content with the matched wp_block's content.

add_filter(
   'render_block',
   function($block_content, $block) {
      if('core/block' !== $block['blockName']) {
         return $block_content;
      }
      if(isset($block['attrs']['postName'])) {
         $post_name = $block['attrs']['postName'];
         $args = array(
            'post_type' => 'wp_block',
            'name' => $post_name
         );
         $results = get_posts($args);
         if(count($results) > 0) {
            $pattern = $results[0];
            $block_content = do_blocks(sprintf(
               '<!-- wp:block {"ref": %d} /-->',
               $pattern->ID
            )); 
         }
      }
      return $block_content;
   }, 10, 2
);

This can allow a theme developer to use synced patterns in their template, patterns, and template parts files, provided the site's database contains a wp_block bearing a matching slug. (As I understand it, this is otherwise infeasible because the pattern's ID may not be identical between site import/exports.) This approach could be coupled with a hook to insert or update the required synced patterns upon the theme's installation, or used alongside a wp-cli import/export procedure that accomplishes the same outcome of inserting "user" patterns into the database. Either way, use of IDs to reference the patterns (and the pitfalls that entails) is avoided.

Perhaps that example is hardly a solution. I do think it is an interesting approach using some of the existing API. With a bit more hackery, it should be possible to have synced patterns inserted via a post's block editor bear the postName attribute, too.

I understand the conversation in this thread to be quite large in scope. There's talk about unifying template parts and patterns, working on the REST API, etc. My comprehension of that stuff isn't great. I've only recently grasped the difference between template parts and patterns (now that I get it, I think the difference is warranted.) I still don't understand why theme pattern files can't be synced, but I suspect it has something to do with the fact that they are stored as posts.

What interests me in the proposal so far is this:

A pattern is referenced by a "slug" in most case (template part slug, pattern slug, or a random slug when created by the user). The slug is universal and is the identifier in the PatternRegistry, which means it works for all of the registration methods of (php api, file, user DB, template part file)

As I see it, adding this attribute accomplishes 90% of what developers like me need without causing any great upheaval in the existing block paradigms. It may also help refocus on the fact that patterns are posts, and that they should be given the same economy other post types get, such as reference by their slug.

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) [Type] Iteration Scoped iteration of an effort from a tracking issue or overview issue ideally for a major release.
8 participants