Closed (fixed)
Project:
Drupal core
Version:
9.2.x-dev
Component:
layout_builder.module
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
24 Feb 2020 at 05:19 UTC
Updated:
19 Feb 2021 at 12:44 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
tim.plunkettOuch, I didn't realize we left this out so completely.
Moving to 9.0 to be able to run tests
Desperately needs #2273381: Convert ContextAwarePluginBase to traits, but embedded the methods directly for now.
Comment #5
tim.plunkettPostponing on the plugin system issue.
Comment #6
larowlanWow, didn't expect a patch on this, just wanted to flag it when I hit it.
Thanks!
Will put in my list.
Comment #7
clayfreemanRebasing the patch from #2 to assume the patch in the linked issue will be merged.
Comment #8
clayfreemanBackporting patch from #7 to 8.9.x branch.
Comment #9
xjmComment #10
clayfreemanThe patch has been updated to seed
Section::getLayout()with contexts fromLayoutBuilderContextTrait::getAvailableContexts($section_storage)to avoid the following exception when attempting to use thelayout_builder.entitycontext for the default layout:This exception was being thrown because the custom contexts provided by Layout Builder via
LayoutBuilderContextTrait::getAvailableContexts()weren't being included in the layout plugin sinceSection::getLayout()was usingcontext.repositoryto get available contexts.To fix this, an additional parameter
array $contexts = []was added toSection::getLayout()to allow contexts to be injected by the caller since this method can't access$section_storageto retrieve contexts from Layout Builder automatically. Each call toSection::getLayout()was then updated to include the additional parameter where possible.While it's not ideal to add this parameter to
Section::getLayout(), I'm not sure that there's a better way to handle this. I'm open to suggestions for how this could be handled better.This brings up a potential pain point for context definition plugins: should they have a canonical way to provide sample values? If so, we could eliminate the need for
SectionStorageInterface::getContextsDuringPreview()and instead rely on plugin-provided sample values. This would enable us to usecontext.repositorywith no repercussions (as far as I can tell) and avoid having to pass contexts toSection::getLayout().Comment #11
tim.plunkettDespite this being blocked on the other issue, if you're actively working on the patch it's better to keep the tests running so we can be sure each change isn't breaking something. For now that means posting "combined" patches with this and the other blocking issue.
Comment #12
clayfreemanNo changes have been made since #10; just reorganizing to facilitate testing.
Comment #14
clayfreemanChanged
ConfigureSectionFormto not pass any contexts intoSection::getLayout()similar to howConfigureBlockFormBasedoesn't pass any contexts intoSectionComponent::getPlugin().This should resolve the test failure from #12.
Comment #15
tim.plunkettShould use the $contexts variable inside the loop
Comment #16
clayfreemanThanks for pointing that out! It looks like I created the variable and everything... just forgot to actually use it.
Comment #17
tim.plunkettIdk if it should be done here or in a follow-up, but this is very important code that is 1:1 lifted from
\Drupal\layout_builder\SectionStorage\SectionStorageDefinition::__construct()and should probably be moved to a trait.The patch looks good to me, and iteration has largely stopped here, so I'm putting this back to postponed for now.
Thanks @clayfreeman!
Comment #18
clayfreemanSounds good.
I agree that a pause is in order on this for now until the blocking issue is merged. Once that's been accepted, I'll pick this back up.
Thanks @tim.plunkett for the work you've done on this issue!
Comment #19
clayfreemanDidn't realize this hadn't already been done, but adding the aforementioned issue.
Comment #20
tim.plunkettBlocker is in. This is just the standalone patch from #16 minus one debug line
Comment #22
clayfreemanSorry for the delayed response.
I've tested this patch against 9.1.0-beta1 and I was able to get my context-dependent layout working.
The patch also seems relatively straightforward without too much room for error from what I can tell.
Comment #23
andypostwould be great to document API changes, probably change record required
Comment #24
tim.plunkettCR at https://www.drupal.org/node/3183338, setting back to RTBC. Thanks for pointing that out @andypost!
Comment #25
andypost@tim.plunkett Thank you! CR looks great
RTBC++
Comment #26
alexpottKinda surprised there's no unit test changes here. But looking at everything I think we're good. It's always hard to tell if everything is covered by tests.
This is not used anywhere.
Comment #27
tim.plunkettSection::getLayout was never tested before because it was a one-line wrapper. When I went to add some, I kept hitting this bug where I couldn't get the test to switch on the instanceof check.
Which led me to realize that the instanceof check was added in a version of the patch before we extended the interface.
Yay for writing tests!
Comment #28
andypostprimary change has BC
somehow there's no way to inject it...
$should_context_applyneeds boolean type-hintComment #29
tim.plunkett1+2)
Section is a domain object, and is not subclassed. It's either created by
new Section()orSection::fromArray().Adding an *optional* parameter to a method that is not backed by any interface is not a BC break.
Because it's a domain object, it has no mechanism for dependency injection.
As you can see, this is not the first method in the class to use Drupal::service()
3)
"needs" is a little strong :)
Also Drupal's coding standards only mention objects and arrays. No guidance/requirement of scalars to be found.
This will be only the 7th bool parameter type in core...
Comment #30
clayfreemanThis looks good to me.
Comment #31
alexpottThis looks good - I've got one more question...
Do we have to worry about an update path here? I.e. if some one is using layouts and the go and press save (without making any changes) on a layout is there any change that their configuration will change? I tried to work this out for myself but I'm not sure either way.
Comment #32
clayfreeman@alexpott It seems that an empty context mapping is added to layouts once this patch is applied, but only after a layout is updated:
I wouldn't anticipate this being an issue, however. (I didn't encounter any errors or hiccoughs while checking for config changes.)
Comment #33
alexpott@clayfreeman #32 means that we need to provide an update function because configuration can change merely by resaving it. We need an update function so, for example, unexpected configuration does not occur on production systems making it harder to merge development changes in. Configuration should always be up-to-date with what would happen if you do:
So I think we need a post update function to use the \Drupal\Core\Config\Entity\ConfigEntityUpdater to re-save all config that could be affected. I think that that is entity view display which are using layout.
Comment #34
clayfreemanAdded an update hook to Layout Builder to add empty context mappings to entity view displays.
Comment #35
tim.plunkettLayoutEntityDisplayInterface extends SectionListInterface, so no need to check both
This shouldn't be explicitly needed, just the fact that it is saved will do whatever we need.
Which means we can return TRUE here, no need to keep looping
Can return FALSE here with the other change.
Honestly, I think the whole callback could be a one-liner:
Comment #36
clayfreemanAttached a patch with the updated interface & conditional.
Comment #37
tim.plunkettFair enough. Thanks!
Comment #38
alexpott@clayfreeman update paths need a test. What's interesting though is this...
If I do this with and without the patch applied I get the same configuration for core.entity_view_display.node.article.default
If I then apply the patch to site that was created without the patch and run the new update method the config gets a context_mapping and a new dependency on layout_discovery! Not sure what is going on here. I think that there is another bug here. If I do the same steps as above on an unpatched site and then do
\Drupal\Core\Entity\Entity\EntityViewDisplay::load('node.article.default')->save();via drush php this will result in the layout_discovery dependency being added.Also given that we have to call
in order to set it I'm confused about how to get an empty context_mapping via the UI. @clayfreeman can you detail the steps you took in #32?
Comment #39
clayfreemanReplication steps on a clean 9.2.x testing environment:
/admin/config/development/configuration/full/exportand click "Export."Now that you have a baseline in place, you can either choose to apply the patch then repeat steps 3 - 8, or run & compare the update result and repeat steps 7 - 8. In either case, you should see the difference in configuration is identical (i.e., a single line difference where the empty
context_mappingvalue is added).I'm not sure why you're seeing anything different; possibly because your replication criteria didn't include steps 3 - 6.
With regard to a test case for the update hook, I'll be researching precedence for how those should be added and attach an updated patch later today.
Comment #40
clayfreeman@alexpott
In trying to write a test for the update path, I discovered the following:
::runUpdates(). It appears that an update forsystemis being ran to uninstall Classy. This causes Layout Builder to attempt to access a nonexistent table because the hack-y install method that these update tests have to use doesn't give Drupal a chance to initialize the module's schema.Without being able to write a test for this update path, my next step was to see if there may be an alternative that doesn't require an update hook; I discovered that if we make the following change to the previous patch, no difference exists between an unpatched & patched site's configuration for layouts without context definitions:
This doesn't really solve the issue per se; it simply avoids setting an empty sequence if there is no context mapping data.
I think @tim.plunkett and I both agree that an update path would be cleaner instead of relying on a NULL default for the context mapping value, but I think it's a decent compromise given the situation.
Configuration differences could still occur with this patch if a layout plugin defines at least one optional context definition, maps a value for it, and subsequently removes the mapping. (The context mapping value under this circumstance would result in an empty array.)
For all existing layouts without context definitions, there is no chance for discrepancy and the update hook can be postponed and addressed in a follow-up issue.
I'm uploading this alternate patch for your consideration, as I'm on holiday starting tomorrow & through next week and will be unavailable to contribute any additional patches during that time.
Comment #41
larowlanThere are commands in core/scripts for generating dumps
Comment #42
alexpottThis is now blocked on landing #3194562: Add database dumps for 9.0.0
Comment #43
clayfreemanUpdating patch with test using 9.0.0 dump.
Comment #44
clayfreemanSince #3194562: Add database dumps for 9.0.0 is now merged, and tests are again passing, this should be ready for additional review.
Comment #45
jeremyvii commented#43 is working for me.
Comment #46
alexpottCommitted 5e7fb73 and pushed to 9.2.x. Thanks!
Removing needs subsystem maintainer review because @tim.plunkett is a subsystem maintainer and okayed the subsystem changes in #24 - the main blocker since then was update path.