-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Allow block use based on post-type or template context #41718
base: trunk
Are you sure you want to change the base?
Conversation
allow block use by post and template type
👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @gigitux! In case you missed it, we'd love to have you join us in our Slack community, where we hold regularly weekly meetings open to anyone to coordinate with each other. If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information. |
…-allow-block-post-type
Hi there! Thanks for exploring this. It would be good to get thoughts from @WordPress/gutenberg-core on this since it is a pretty foundational API. I think it would be better to design this API in a generic way that's compatible with all entity types. We have several entity types right now: templates, template parts, reusable blocks, widget areas, etc. Plugins may also register their own custom post types. Perhaps this could be done by the allow list accepting tokens of the form // Only allow block to be inserted into the 'archive' template.
allow: [ 'wp_template:archive' ]
// Only allow block to be inserted into a 'page' cpt.
allow: [ 'page' ]
// Only allow block to be inserted into certain products.
allow: [ 'product:tapered-jeans', 'product:crew-t-shirt', 'product:linen-shirt' ] Lastly, we have an existing Instead of adding new // Only allow block to be inserted into a 'core/columns' block, the 'archive' template, or a 'page' cpt.
parent: [ 'core/columns', 'wp_template:archive', 'page' ], |
Hi! I have some doubts about the implementation that I did and if the use-cases that I highlight should be handled in a different way. |
Oh cool I hadn't seen #41398. You're right that consistently there would be good. Maybe |
With the current approach, I think there are going to be some issues around adding WordPress specific terms like 'post type' and 'template' to generic parts of the Block API. While developed by WordPress, the block editor is not only for use in WordPress, it's actively used by other CMSs and applications where those concepts don't mean anything. It might be ok for WordPress' block editors to progressively enhance the block API with these terms. It'd be good to get some wider feedback about that possibility from other maintainers. For now, I think it'd be good to avoid touching some packages like 'blocks' in this PR if possible. If that package does need to be modified, it'd be good to think about whether that can be achieved in a way that's non-WordPress specific, and that might also serve the needs of other block editor implementors outside of WordPress. |
Thanks for exploring this @gigitux! This is a complex issue indeed and there are many similar existent APIs that we should explore to consolidate like:
I'm a bit concerned that if we keep adding more flags and try to make all these work together is going to be difficult to maintain and reason with. Also any new APIs should be integrated into In addition to the above this can't happen on editor settings level because for example In my mind this is a problem of proper context detection. Noting I don't have a clear solution right now but we do have some information in context already. Through block context we know the So, do you think we can do something with the above? Can we think something more robust than |
@ntsekouras We need a way to say:
What level of extensibility is Gutenberg aiming to provide? Should be possible to create a As for the technical details... It's a tree validation problemIn other words, there are valid and invalid component trees and the editor should prevent the user from creating an invalid one, e.g. by disabling the inserter in specific cases. A valid tree could look like this:
While an invalid tree could look like this:
HTML solved it top-downThis looks a lot like HTML and some of the same tools may apply. For example, HTML4 used a dtd file:
That's complex and excessive but also limiting and so HTML5 doesn't use DTDs anymore. There are popular HTML5 validators based on schema (I removed the attributes):
The thing is, these DTDs and schemas are designed top-down. There's no need to have an API for extenders to update the allowed parents, contexts, and such. Gutenberg extensibility requires a bottom-up solutionSince we're reasoning about a validity of a tree, CSS and XPath selectors would provide infinite flexibility. For example, the Columns block could define the following specification in block.json: {
"treeAssertions": [
"count(/*) = count(/Column)" // Only the instances of the Column block are allowed as direct children
]
} Then, the singular Column block could do the following: {
"treeAssertions": [
"name(/parent::*) = 'Columns'" // Only the Columns block is allowed as the parent
]
} Do we need infinite flexibility, though? Because it comes at the price of complexity – XPath is harder to write than vanilla JSON. This comes back to the big question I asked earlier: What level of extensibility is Gutenberg aiming to provide? |
I'm definitely worried about the complexity this solution creates and how deceitfully simple it looks at face value. It makes me wonder just how bad the existing situation is: we have the claim that we have to unregister a block to avoid seeing it in the block editor but we also have the other option of only registering it when we want it to appear. There are also simpler solutions that are less effective in principle but isolate the complexity and dramatically simplify how the pieces have to fit together: make the block warn if it's used in the wrong context by checking in Keep in mind in all of the attempts to prevent people from adding the content that they want that even with our best attempts at preventing that they can still insert any block anywhere in any context by editing the text of Is this as big of a problem as we think it is? Can we accomplish this via other mechanisms, such as improving the search ranking in the block inserter to de-prioritize blocks that we think shouldn't appear in a given post type or template? Can we accomplish this by adding an indicator that we recommend people not use this block where they have, that we found that they are using it in a way we didn't want them to or that it could behave differently than it usually does given its context? Can we solve this without introducing new systems or vocabulary into the already-complicated block API? |
Conceptually, this looks more and more like something that should exist at the post type registration level, either controlled by the one entity governing the post type registration call or by a plugin that interacts with it. Blocks shouldn't have to be themselves aware of it given it creates complicated and opaque meshes — for example, when a pluginA says blockX should be on postTypeY and pluginB wants to say it should also be in postTypeZ. That's best handled at a layer above blocks, where post types have access to the pool of available blocks, conditions, etc, and can decide which ones to initialize and which ones to exclude. This also helps keep the block API cleaner from WordPress specific concerns and the complicated mixture than can ensure from it. Templates and template parts is a bit different, given they are essentially block ancestors like any other block. We should probably discuss some |
As @ntsekouras referred we already have many ways of restricting what blocks can be inserted. In the end there will always be a complex scenario that our declarative API's don't support. Could we use the filter canInsertBlockType to check the template where the block is being inserted and restrict based on that avoiding the need for a new API? |
What?
This PR allows making the block visible only on specific post types and/or specific templates. Fix #41062.
Why?
The current way to hide blocks based on context is a little bit tricky (how to do this is in the description of #41062). For
WooCommerce Blocks
, we need this feature because we want to enable specific blocks only for a specific template (woocommerce/woocommerce-blocks#5193). We tried as suggested (woocommerce/woocommerce-blocks#5637) on #41062, but we would prefer to have a better way to do this on the Gutenberg side.How?
I'm pretty new to Gutenberg codebase: I noticed that all the logic around the blocks and the
Inserter Block
is contained in@wordpress/block-editor
package. The filter that I'm trying to add has to be aware of WordPress context and in accordance with the modularity documentation this package is independent of the WordPress ecosystem.This is the only way that I found to implement this feature without a huge refactor. I'm not sure that is the correct way to go, so I'm open to feedback and hints :)
With this implementation, there are some use cases that I want to highlight:
allowForPostTypes
orallowForTemplates
it should be not possible to add on that post/page/template, the added block will be still visible, but if the user removes the block, this latter will not be able to re-added.Testing Instructions
In this PR, there are changes on the
block.json
of theCode Block
. This is just to speed up the testing, but obviously, these changes will not be included in the final code. In accordance with the changes the block it should be visible only on:On the WordPress codebase, I added in this array, these two lines:
After that check out this branch:
Code
block: it should be not visible.Code
block: it should be visible.Home
template.Code
block: it should be not visible.Archive
template .Code
block: it should be visible.