Problem/Motivation
Follow up to #3041659: Remove the layout tab from translations because Layout Builder does not support translations yet
That issue does not actually update existing layout fields to be non-translatable. New layout fields for bundles though will be marked as non-translatable.
#3041659 has detailed summary of why we cannot update the fields automatically without inspected the sites current configuration/content.
Proposed resolution
Update the layout fields to non translatable on a per bundle basis.
If all bundles that have layout overrides enabled for an entity type are able to have their fields updated to be non-translatable then update the layout field storage for the entity type to also be non-translatable.
It is not yet determine on what conditions we will be able to update a layout field for a bundle but possible solutions are
!\Drupal::languageManager()->isMultilingual()!\Drupal::moduleHandler()->moduleExists('content_translation')- There are no translations for a bundle,
!default_langcode = 0(they enable translations but never used them) - There no layout overrides for the bundle(they enable overrides but never used them)
- No single entity, across all of its revisions, has both a translation and a override
1,2 have the problem that may have translations that are orphaned because you disable a language but will be available if you re-add the same language. But this is probably a problem with content_translation in general. If you disable content translation are the field rows cleared out for each entity each time you save the entity? If so this would the same behavior. Will EntityQuery pick up these rows anyways?
3,4 seem the simplest query and probably could be queried by EntityQuery and we could update the field when either condition passes.
5. may not be possible to find with EntityQuery so we would have construct the query manually, #3041659-50: Remove the layout tab from translations because Layout Builder does not support translations yet has a version of this query tha t might work and has an update path test. But currently if testing 2 different cases when the bundle should not be an updated. It does not a test case for when bundle should be updated, no single entity has both a translation and a layout override.
3,4 won't be able to update as many sites but it probably safer because is simpler. It also has the advantage of being easier to understand so the documentation could shorter, more understandable. Also site owners would probably able to understand and predict whether there sites would match these conditions.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | interdiff-11-12.txt | 2.88 KB | tedbow |
| #12 | 3043651-12.patch | 35.86 KB | tedbow |
| #10 | 3043651-update-10.patch | 35.81 KB | tedbow |
| #10 | interdiff-8-10.txt | 5.4 KB | tedbow |
| #8 | 3043651-8.patch | 34.53 KB | tedbow |
Comments
Comment #2
tim.plunkettPer discussion, tagging for now.
Comment #3
effulgentsia commentedDoing 3 and 4 is probably best. Those are simple queries. However, we'd need adequate test coverage for the different cases. So long as we're not blocked on issues with getting update path fixtures for these working, I think it's a great approach.
If the test fixtures for that are too problematic, and we want to go the route of 2 (or an and condition of 1 and 2), then we're in luck, because of #3043650: Exception when uninstalling CT when there are existing translations. If it weren't for that, there'd be the risk of orphaned translations, but since you can't uninstall CT if you have existing translations, we're (sort of) covered. Kind of sketchy relying on the fact that CT has a critical bug though. And I suppose there's the edge case possibility of someone having translations that they create via some other module (not via CT), though that's what anding the if with 1 would mitigate.
Comment #4
tedbowHere is try at 3 and 4.
some snippets from the patch
Right now it only has 2 testes. Will add more
Currently I am only testing that field gets updated not any functionality of the entities. We may want to add that but wanted to keep as simple as possible for now.
Comment #5
tedbowI wanted to varying the fixture set by test cases for which bundles have default and layouts. I don't think this is possible with a data provider method so I created a base class and then subclassed for each test case. This allows setting a
$layoutBuilderTestCasesthat fixture has access to.This reduces the number of fixture files that need to be setup.
Comment #6
xjmComment #7
plachThis is looking great, the base test class is a nifty solution! I manually tested the fixtures by running tests and stopping them before the
::runUpdates()call: after manually running the update everything in the UI and in the database looks as expected.If we
array_intersect()the two full result sets we are actually implementing solution 5, I think. IMO we could do that, as this would further reduce the cases that are left out of luck. However we may need to pay attention to memory consumption, if the two result sets are very big (e.g. one million rows), here's the output of a test script I quickly put together:Nit: let's use regular inline comments (//) here.
Unused
I think we can remove this line, it's not used in the two tests and makes things slightly confusing.
I couldn't help but noticing we are missing case 2: are you working on another test? :)
Can we use "data provider" instead, just in case some weird parsing bug leads to even weirder test failures?
Nit: extra newline :)
Comment #8
tedbow@plach thanks for review.
Thanks! I will wasn't sure there was a better way but I think it makes the test fixtures simpler and adding more tests in the future if need not so drastic
LayoutFieldTranslateUpdateConfigandLayoutFieldTranslateUpdateConfigAndStorageto reflect that 1 case can update both the field config and the field storage.Comment #9
plachPatch looks good to me and works as advertised. This is RTBC as far as I'm concerned, unless we want to try and implement solution 5.
Comment #10
tedbowI went over the patch with @effulgentsia(thanks!) and here are some changes from that.
All of the changes are refactoring and adding better comments to the changes to layout_builder.post_update.php.
There 3 only functional changes
->accessCheck(FALSE)to the queries to ensure we check all entities$entity_type->isTranslatable()and determining there are no translations if it is not.$field_config->isTranslatable()before checking for translations or layout. This allows us to still update the field storage if a bundle was already configured to be non-translatable.Comment #11
tim.plunkettWould make me feel better if this started as FALSE and was later explicitly set to TRUE
"all layout fields" isn't it just one?
Nit: The entity type ID
This is such a nice clean way to do this. +1
+1 to this being RTBC after those changes
Comment #12
tedbow@tim.plunkett thanks for the review!
$non_translatable_bundle_count = 0;Then each time we find that is either already non-translatable or that we update
$non_translatable_bundle_count++;Then we only update the storage if
if (count($field_infos[OverridesSectionStorage::FIELD_NAME]['bundles']) === $non_translatable_bundle_count) {Luckily we have test coverage for a cases for where we should and should NOT update the storage.
Comment #13
tim.plunkettWorks for me! Thanks so much
Adding credit
Comment #14
plachWouldn't it make sense to perform the same check on the field storage and skip looping over all the bundles if that's already FALSE?
Comment #17
plach@effulgentsia pointed out in Slack that unless some custom code changed the storage to FALSE it would always be TRUE, so I think committing a follow-up is not worth the effort.
Comment #18
effulgentsia commentedPushed to 8.8.x and 8.7.x.
The biggest benefit of this patch is that it updates things nicely for monolingual sites, so I updated the CR accordingly: https://www.drupal.org/node/3043164/revisions/view/11360219/11361603.
That it also handles some other easy cases, such as a bundle that enables layout overrides but doesn't have any, is a bonus.