Problem/Motivation
Currently EntityConverter has an option to load the latest revision. This is used mainly with entity forms to ensure draft revisions can be edited, instead of the default revision. However, this does not work with translated entities, because every translation draft has a dedicated pending revision, only one of which is the latest revision at any time.
Proposed resolution
To properly support multilingual content moderation, we need to load in entity forms and related routes the latest translation-affecting revision instead of the latest revision, this guarantees every translation draft can be loaded in the related entity form. This is also fully BC with respect to the original behavior, since for non-translated entities the latest translation-affecting revision and the latest revision are the same.
Remaining tasks
- Validate the proposed solution
- Write a patch
- Reviews
User interface changes
None
API changes
None
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #25 | entity-ml_entity_converter-2938895-25.patch | 17.33 KB | plach |
Comments
Comment #2
wim leersThis is a hard blocker for #2860097: Ensure that content translations can be moderated independently.
Comment #3
plachHere's a patch, split-off from #2860097-103: Ensure that content translations can be moderated independently. The interdiff is to address #105.
Comment #4
plachWe need a follow-up for this deprecation.
We could use additional test coverage here.
Comment #5
wim leers#4.1: done: #2938929: Make the entity repository required for EntityConverter.
Comment #6
plachThis should address the outstanding issues and #2860097-105: Ensure that content translations can be moderated independently.2: Wim and I discussed this and agreed that improving the documentation should be enough to address his concerns.
Comment #7
plachWrong interdiff
Comment #8
wim leersNW mostly for nits, then this is RTBC!
Supernit: s/the converter/this converter/
s/fall fall/fall/ 😆
Nit: s/skipping/omitting/
Nit:
ContainerInterface::classwould be slightly better.Do we actually need this? Will a core test fail if we don't add this? (We're only supposed to add this for deprecations that would otherwise make core tests fail. And AFAICT we're already updating all parameter converters that subclass
EntityConverterhere.)Comment #9
plachComment #10
wim leersComment #12
plachLet's try this.
Comment #13
plachActually, I meant this.
Comment #14
wim leers#13 looks good.
Comment #15
wim leersComment #16
effulgentsia commentedAre we sure we want to make the language manager (effectively) required for all entity converters? It's only needed for entities that are translatable, revisionable, and where there's a route flag asking for the latest revision. In which case, why require the parameter for all other cases, like all config entity param converters? What about adding a protected method,
languageManager(), and trigger the deprecation warning from there, so only when used?Comment #17
plachBriefly discussed this with @effulgentsia in Slack, he suggested to trigger the deprecation error at runtime so we don't need to update config entity converters.
Here's a PoC, to be completed.
Comment #18
effulgentsia commentedThanks. The interdiff looks great. I think that means we can also remove the changes to
AdminPathConfigEntityConverter,ViewUIConverter, and maybe others from the patch?Not needed.
Perhaps change the message to "The language manager parameter has been added to EntityConverter since version 8.5.0 and will be made required in version 9.0.0 when requesting the latest translation-affected revision of an entity."?
Comment #20
plachThe patch should be now complete.
Comment #21
wim leersThis change is unnecessary.
When can this return
NULL?Let's mark this @internal.
AFAICT thanks to the changes proposed by @effulgentsia and implemented now, this change is also no longer necessary.
(It will be necessary in #2860097: Ensure that content translations can be moderated independently though AFAICT.)
Comment #22
plach1: Fixed
2: Fixed
3: Fixed
4: Correct, let's keep it here, so we don't have to touch this code again over there, where it would be more confusing.
Comment #23
wim leersComment #24
plachThis will need a change record update once committed.
Comment #25
plachReverted a no longer needed change.
Comment #26
effulgentsia commented#25 interdiff is trivial, so back to RTBC.
Comment #29
effulgentsia commentedAdding reviewer credit for @Wim Leers, and also for @timmillwood and @hchonov for their work on #2860097: Ensure that content translations can be moderated independently from which this was split.
Comment #32
effulgentsia commentedPushed to 8.6.x and cherry picked to 8.5.x.
Comment #33
effulgentsia commentedPer #2860097-111: Ensure that content translations can be moderated independently, this might be a controversial change. I'll await comments from @hchonov and @plach, but I'm considering reverting just these lines if there isn't agreement about them yet.
Comment #34
hchonov@plach proposed in #2860097-115: Ensure that content translations can be moderated independently:
and I've responded to this in #2860097-121: Ensure that content translations can be moderated independently:
So I think that those changes to the content translation routes should be reverted.
I have one remark and one question about the patch that got in:
As we are executing a query to retrieve the revision ID, then we don't necessary have to load the default entity revision. The code could be easy converted to skip loading the default revision if it isn't needed.
Why do we provide BC here instead of enforcing the language parameter to be included through DI? I've found the following in https://www.drupal.org/core/d8-bc-policy:
If I am not mistaken, then we don't have to provide BC when altering the constructor.
Comment #35
wim leers#34.2: the BC policy is the theory, in practice we also look at "likely real-world disruption". In this case, with half a dozen subclasses in core alone, it is very likely that we'd disrupt contrib/custom modules. In this case, and many cases before it, we've therefore opted to make new constructor arguments optional, and then automatically load them.
Comment #36
plachThis was done to keep around an optimization @catch suggested in the parent issue: #2865616-80: Add an option for EntityConverter to load the latest entity revision and fix all entity forms to use this option..
Comment #37
hchonov@plach, if it happens that the current default revision and the forward revisions are different, which is pretty likely to be the case when using forward revisions, then it will always happen that we load two entity objects. Optimizations for loading only one entity object by ID and by revisions ID if it is the same revision both point to are done in #2620980: Add static and persistent caching to ContentEntityStorageBase::loadRevision() and could be further optmized. The patch there will load only one entity from the persistent cache if a revision is first loaded by
::loadRevision('revision_ID_of_the_current_default_revision')and then the entity is loaded through::load('entity_id').Comment #38
plachGood to know :)
I believe that optimization was done in the light of the fact that right now loading the default revision is way less expensive than loading any other one. Of course the issue above will change that.
Comment #39
effulgentsia commentedI posted a patch to revert them in #2939247: Revert Content Translation routes to act on default rather than latest revisions.