Problem/Motivation
Labelling this as a bug for now, but feel free to change it. It certainly feels like a bug to me but #3052042: If an inline block has been edited outside of layout builder it can't be edited in layout builder and the code that explicitly allows this says otherwise.
The problem is, when a block is created via Layout builder (making it inline/non-reusable) and the block is referenced by a node (or whatever entity type) revision that the user can also edit, that user is able to edit the block through the entity.block_content.canonical route.
The code path that lets this happen is from the access control handler into the inline block dependency subscriber
Why is this a bug? It just doesn't seem to fit with what the rest of the solution around inline blocks is trying to achieve. For instance:
1) The block is explicitly filtered out of the block content collection
2) When the block is edited via that UI, the user is then taken to previously mentioned collection screen where the block isn't listed
3) If the user tries to edit the block again they get access denied because now the new revision is no longer referenced by the node revision they can access and the event subscriber doesn't return a dependency which returns access denied
4) The changes the user made are NEVER seen because nothing references that revision.
5) It causes bugs like #3052042: If an inline block has been edited outside of layout builder it can't be edited in layout builder
Proposed resolution
Deny access from editing inline blocks via any UI except layout builder.
Remaining tasks
- Agree this is a bug
- Fix 'er up
User interface changes
Remove ability to edit inline blocks via the block content UI.
API changes
TBD
Data model changes
Hopefully none.
Release notes snippet
TBD
Issue fork drupal-3075308
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
acbramley commentedComment #3
chris burge commentedMy understanding is that inline blocks were designed to be used with one and only one host entity. This is evidenced by some of the reasons listed in the issue description. That said, I think there is significant value is being able to edit inline blocks outside of Layout Builder. Contextual links is a good example. When contextual links are enabled with #3020876: Contextual links of reusable content blocks are not displayed when rendering entities built via Layout Builder, a user can hover over a block and access an edit link without leaving the current view mode. That's a real UX improvement.
I'd reframe this issue from 'Editing inline blocks outside of Layout Builder causes undesired behavior and thus must be prohibited' to 'Are there benefits to editing inline blocks outside of Layout Builder and, if so, how can the undesired behavior be fixed?'.
Comment #4
acbramley commented@Chris Burge true, but editing it outside of LB means that there is no way to create a new revision of the host entity to reference the new block revision as you are no longer in that context.
The UX of editing the block in the normal UI is definitely a plus as the canvas sidebar is pretty broken without some custom styles with anything other than very basic fields. I wonder if something like https://www.drupal.org/project/layout_builder_modal is a more ideal approach for core as well, it has worked really well for me so far, especially when the admin theme is used to render the modal form.
Comment #6
peterhebert commentedAs a content editor I don't care whether or not the block has been created inline or is reusable, and I probably don't even know the difference between the two. I just want my contextual links to "Edit" the block, no matter how or where it was originally created. The architectural nuances should not get in the way of a cohesive and understandable UI. My 2 cents.
Comment #7
sam152 commentedI don't think there will be any reasonable way this can be allowed and these issues can be remedied. Any change to an inline block means some revision of the host entity must be updated to point to some other revision of the inline block. It's not possible to save a revision of the host entity, without the user being granted access to do so and without the same user making explicit choices.
For example, consider a moderated page with layout builder and inline blocks. If I modify an inline block outside of layout builder:
The same kind of questions apply to non-moderated content and decisions users usually make on entity forms like "should this be a new revision" and "what should be the revision log message for this revision".
Overall, I don't think specifically loading an inline block in it's own form outside of layout builder could be done correctly, with no data integrity or access bypass issues without enormous effort for a marginal gain.
Why not instead create contextual links that open the layout builder form, then launch the configuration screen for that inline block? Roughly the the same experience, with the added benefit of having all the above problems disappear and you also get layout builders preview facility.
Comment #8
tim.plunkettComment #9
chris burge commentedI think we should remain open to the idea of reusable inline blocks. From the editor's point of view, they can edit the block in a place it's being used. The alternative to make them use the custom block library, which requires the 'administer blocks' permission, which I don't give editors for obvious reasons.
This was solved in D7 with Fieldable Panels Panes. A pane can be designated as either reusable or not. After creation, there's no changing that designation. If it's non-reusable, then everything works pretty much as Layout Builder and Inline Blocks works now. They're tied together. If it's reusable, then the host entity's reference is to whatever the current published revision of the pane happens to be; it's not tied to a specific revision ID. As a result, there's no need to update a host entity when the reusuable pane is updated - no matter where it's updated.
Comment #10
christian.wiedemann commentedI created a contrib (Layout Builder Inline Block Quick Edit) module that tries to face this problem. It "overwrites" the block revisions with the latest block revisions on load for draft layout entities and activates the contextual links. The idea behind is not to update the host entity when a new block revision is created, but to load the right revision in dynamic manner on load.
Quick edit checks, if a new revision is needed, before saving.
It is quite hacky and more a technical preview - but maybe it could be a solution in order to delegate the revision loading to contrib.
Comment #14
tancThis would definitely be a good/better editor experience. If contextual links are allowed on inline blocks (currently they are not, due to this issue) the edit link could (or should in my opinion) open the layout builder form and the inline blocks' edit form.
Comment #15
tancI thought I'd see if I could do a proof of concept but I realised just how much layout builder code there is and while I managed to get a hard coded example up and running I wasn't able to have something flexible worth offering as a patch. Probably someone who knows LB inside out needs to take a look at implementing this.
The things I noted are:
contextual_linksgroup with just the update route in it (maybe renamed to edit) so only that link shows up and not the other LB move or delete links.At the very least, from a user's perspective, the block's quick edit link should be available but not the block edit link. Then an ideal feature update would be to include the edit link but have it opening the layout builder on the block edit/update form.
Comment #17
Anonymous (not verified) commentedConsidering previous comments regarding versioning and moderated content, this approach seems the most reasonable and stable in the long run. My interest is like others on this thread -- primarily from the perspective of the content editors. They are slowly learning the difference between reusable and inline blocks, and how to create the different blocks that they need. Anything that improves the workflow would be very much appreciated.
Comment #22
mortona2k commentedI got this started from the editing side.
With the issue fork, you can add ?edit=UUID-FOR-THE-BLOCK-TO-EDIT, and layout builder will open the right block form on load.
I'm not sure what it will take to link to this, but if we can get contextual links added, it should work.
Looking for feedback on the approach and query parameter name.
I think the ability to edit inline blocks from the front end makes the most sense for UX. I would like to see contextual links that bring up a modal. 90% of the time I'm an admin editing the latest revision and I want to save and create a revision according to the "create revision by default" setting. There may need to be some configuration options, and a confirmation form to make decisions about things depending on what state it's in. It sounds like there are a pile of technical reasons why this is hard, but it would be great to start structuring the basics and work out the edge cases over time.
Should the issue title be changed? I think it should now be "Add contextual link to inline blocks to edit in layout builder".
This issue component is set as block_content.module, but I think this applies to all inline blocks in layout builder.
Comment #23
acbramley commentedAll these ideas are great, but this issue needs to focus on denying access to edit a block that is reusable from the UI (i.e
admin/content/block/IDfor all the reasons explained in #7.Re #9 I agree we should be open to it, but not as part of this issue. Editors already have the choice of inline vs reusable, they just have to create them in different locations. Perhaps we could have a "convert to reusable" feature or something, but again that's for another issue.
Comment #26
acbramley commentedPosted an MR with a potential solution. Still needs tests.
Comment #27
acbramley commentedComment #28
smustgrave commentedSince this could be a behavior change from some, probably will need a CR I would assume. Since we are denying something that was previously allowed.
Comment #29
acbramley commentedhttps://www.drupal.org/node/3527795
Comment #30
smustgrave commentedCR reads fine to me.
Ran test only change and got
Manually test on an Umami install I had
1. In the article content type Full content layout builder I added a test block
2. I went to /admin/content/block/5 where I can see the block and make edits
3. Added MR
4. That route is no longer accessible
Change looks good to me.
Comment #32
catchThis makes sense to me, tagging needs follow-up for the idea of contextual links from the block going back to the layout builder edit page. But also I wonder what XB/Canvas is going to end up doing with things like that whether for embedded entities or SDC content.
Committed/pushed to 11.x, thanks!
Comment #35
godotislateThink this commit might have broken HEAD:
Comment #37
godotislatehttps://git.drupalcode.org/project/drupal/-/merge_requests/13214 to fix the deprecation of the test annotation.
Comment #38
phenaproximaThis broke HEAD; unit tests are not passing because of the deprecation. The follow-up MR needs to be merged tout-de-suite.
Comment #39
mondrakecritical while head testing is broken
Comment #41
catchThanks for the quick MR. Committed/pushed to 11.x, thanks!