Problem/Motivation

Steps to reproduce:

  1. Enable CM and layout.
  2. Enable moderation on nodes, enable customising layouts on individual nodes.
  3. Create a published item of content.
  4. Create a new draft of that content, make some changes.
  5. Change some part of the layout for that item of content.
  6. Data in the pending revision is overridden by a new default revision, although it is still available in the DB.

Proposed resolution

Adapt the new API from #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Sam152 created an issue. See original summary.

larowlan’s picture

Priority: Normal » Major
tim.plunkett’s picture

larowlan’s picture

My thinking here is that LB should work with CM, in so far as a new layout should be a new pending revision.

Sam152’s picture

If layouts simply loaded the latest revision:

  • If an item of content didn't have any draft content, layouts would be saved as default and published (an unchanged moderation_state value would enforce that).
  • If an item of content had draft changes, those would appear as content in the layout builder, layout changes would be saved in a pending revision along with the draft content.
  • Once an item of content had transitioned to published, the layout would be published along with it.

The only question is, who is responsible for doing that.

Sam152’s picture

Issue summary: View changes

Added steps to reproduce.

Sam152’s picture

Issue summary: View changes
larowlan’s picture

Priority: Major » Critical

Data loss makes this critical

larowlan’s picture

Component: content_moderation.module » layout.module

Should be job of LB?

Sam152’s picture

Issue summary: View changes
tim.plunkett’s picture

Issue tags: +Blocks-Layouts, +Needs tests

Most of \Drupal\Core\ParamConverter\EntityConverter has nothing to do with param converters, it's just "the right way to load entities for editing/displaying".
If that was abstracted to a service, I think the right method calls added to \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::getSectionListFromId() would solve this.

Sam152’s picture

@larowlan it's only the job of layout builder if we make a decision with regards to how to other modules should treat pending revisions. Currently without a path forward on that, CM is already required to hook into other parts of core to enforce those semantics.

tim.plunkett’s picture

Status: Active » Needs review
FileSize
3.29 KB

This REALLY needs functional tests to validate that it's the behavior we want.
But this might be a start, as I understand the problem?

Status: Needs review » Needs work

The last submitted patch, 13: 2942675-layout_revision-12.patch, failed testing. View results

Sam152’s picture

Issue summary: View changes
Sam152’s picture

Issue summary: View changes
tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
3.34 KB

Oops, had other code applied locally.

Anyway, I think this should NOT be Layout Builder's responsibility at all. There should be an API method on a service for loading a mutable entity, and we should call that instead of $this->entityTypeManager->getStorage($entity_type_id)->load($entity_id); which should be banned from usage in code that presents user-facing data.

EclipseGc’s picture

Tim brought up the comparison of get() vs getEditable() for config objects, and that really resonated as a good analogy to me on this topic. I think it's fine that layout_builder acknowledges that it needs to make concessions to some other system in order to get the particular version of the entity it needs, but that could be revision, or revision of a particular language, or any number of unforeseen criteria that may come to light at some point in the future. As it is, this patch hard-codes the logic which should probably exist in a real api somewhere. If we had a central service that could negotiate that, I bet stuff like content_moderation would get a lot easier and we'd not have to play whack-a-mole with all the new modules that come along that we wish we could integrate with.

Eclipse

plach’s picture

Issue summary: View changes

Updated the IS to clarify that we are not talking about data loss, but pending revision data being overridden by new default revision data.

In that light I'm not sure this should be critical, given that Layout Builder is still experimental. Not changing the priority, since this will for sure be discussed during the next triage call.

plach’s picture

Btw, what #17 is suggesting looks very similar to what Sam is suggesting in the OP. Unfortunately, even if we had that, it still one more concept to deal with, but I'm afraid there's no way around that.

plach’s picture

+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
@@ -126,7 +128,20 @@ public function extractIdFromRoute($value, $definition, $name, array $defaults)
+        $revision_id = $entity_storage->getLatestRevisionId($entity->id());

Btw, this is not even correct from the multilingual perspective. So one more reason to add an API to encapsulate this logic.

tim.plunkett’s picture

Here's what I think Layout Builder needs. The rest is up to Drupal\Core\Entity to solve.

Status: Needs review » Needs work

The last submitted patch, 22: 2942675-layout_entity_thing-22.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

tim.plunkett’s picture

tim.plunkett’s picture

Component: layout.module » layout_builder.module
Sam152’s picture

Title: Content moderation doesn't hook into layout builder to alter its behavior with regards to pending revisions. » Layout builder should load the latest revision of an entity until core provides and API for loading an edit-revision
Issue summary: View changes

Repurposing this issue based on the latest discussion in #2940575: Document the scope and purpose of pending revisions.

Sam152’s picture

Status: Postponed » Needs work
plach’s picture

Title: Layout builder should load the latest revision of an entity until core provides and API for loading an edit-revision » Layout builder should load the latest revision of an entity until core provides and API for loading the active revision

Let's start using the "active revision" terminology :)

tim.plunkett’s picture

Issue tags: +sprint

Tagging as this is currently on our shortlist.

tim.plunkett’s picture

Issue tags: -sprint

No one is actively working on this.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Sam152’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
4.3 KB

Adding a test for the integration between layout builder and content moderation. Should be useful regardless of the solution which ends up making these two work together.

Status: Needs review » Needs work

The last submitted patch, 32: 2942675-32_TEST_ONLY.patch, failed testing. View results

xjm’s picture

Priority: Major » Critical

I think this is still critical, because even if #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing is addressed the data integrity issue is still there until LB and/or CM implement it.

Sam152’s picture

Status: Needs work » Postponed

There was some discussion at Drupal Europe which impacts the layout builder/content moderation integration, which I summarised in the issue summary here: #3004536: Move the Layout Builder UI into an entity form for better integration with other content authoring modules and core features.

To quote the part relevant to content moderation:

I believe the existing proposals to integrate with layout builder fall short because:

  • The layout override form is the encouraged mechanism for authoring new content.
  • Applying a moderation workflow to fields on the entity is redundant if those fields can be replaced with a non-reusable block and skip moderation altogether.
  • If a user transitions an item of content to state "Foo", they are not necessarily allowed to create new content revisions while leaving the state unchanged (think of something going into review, with an author no longer able to make changes to that content until a review has been completed).

The only way I see these two modules integrating in a way that is true to the sprit of both feature sets: rich content driven layouts/moderated content workflows, is if:

  • Entity "update" access is respected. (see related issue)
  • The latest revision is loaded. (see related issue)
  • The same moderation state transition widget is visible and available when saving the layout override form which allows the authoring of new content. (no related issue in discussion)

I believe if the layout override page was an entity form, we would almost get this level of integration automatically/for free.

I think it makes sense to postpone this issue on some discussion over there. If it turns out the proposal is not viable, we'll need to pick this back up.

tim.plunkett’s picture

Will read the above issue.

nadavoid’s picture

Is there a new temporary shim to help with this problem? The temporary shim being to have layout builder always load the latest revision.

I was using the patch in #17 (https://www.drupal.org/files/issues/2942675-layout_revision-15.patch), but it no longer applies to the latest version of core, currently 8.6.7. Also, manually applying its updates didn't make any difference since the method affected is deprecated and layout builder is apparently no longer using these deprecated methods.

The patch in #22 (https://www.drupal.org/files/issues/2942675-layout_entity_thing-22.patch) doesn't apply either. It looks like it prepares for a solution, but on its own, doesn't provide a workaround.

tim.plunkett’s picture

nadavoid’s picture

Thank you for the reroll Tim! I've successfully applied it on top of the patch in #2986394: 2.x patch reroll issue (I'm using lightning which includes lightning layout), and it seems to be working as expected now. I realize this is kind of a superficial fix to a really tricky problem, so I'll try to follow along with the other related issues.

Pancho’s picture

Title: Layout builder should load the latest revision of an entity until core provides and API for loading the active revision » Layout builder should load the latest revision of an entity until core provides an API for loading the active revision

typo

tim.plunkett’s picture

Status: Postponed » Needs review
FileSize
23.52 KB

Here's a more heavy handed approach building off of #2942907-84: Entity system does not provide an API for retrieving an entity variant that is safe for editing.
Going to use this patch alongside other issues to help prove their test coverage.

Status: Needs review » Needs work

The last submitted patch, 41: 2942675-decorator-41.patch, failed testing. View results

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
21.64 KB
4.01 KB

Accidentally included the test from #2973860: When there is an entity forward revision for Content Moderation and a layout override is saved the revision is no longer latest here. Removing that.
Also changing the prophecy until the new methods are on the interface.

Sam152’s picture

@tim.plunkett Are you intending for this to be committed or do you consider #2942907: Entity system does not provide an API for retrieving an entity variant that is safe for editing a blocker?

I'm assuming a committer would apply the same level of scrutiny to the entity repository changes here, so this patch being ready would essentially mean the blocker is also ready for commit?

tim.plunkett’s picture

I'm not sure how hard to push on this.
Mostly it's an easier means for other issues to be tested than having to apply both the most recent version of that patch plus the internal changes, but updated for the method names du jour.

The internals of the other issue haven't changed in a bit.

This is also an escape hatch if the other issue stalls out and we need something to help fix all these stable blockers.

tim.plunkett’s picture

Status: Needs review » Postponed
tim.plunkett’s picture

Title: Layout builder should load the latest revision of an entity until core provides an API for loading the active revision » Layout builder should load the latest revision of an entity using the new core API for loading the active revision
Status: Postponed » Active
tim.plunkett’s picture

Status: Active » Needs review
FileSize
9.78 KB
johnwebdev’s picture

We could commit as-is, but I'd definitely prefer we get the test coverage from the issues that had been blocked by this API with us.

Patch looks great.

Sam152’s picture

Status: Needs review » Reviewed & tested by the community

Each issue that depends on this issue will have it's own test coverage which will include both implicit test coverage for this issue as well as the logic within the new API itself. Along with the OverridesSectionStorageTest unit test and all the existing functional testing going green, I think the test coverage is okay.

Tentatively RTBC, will see what committers think.

The last submitted patch, 38: 2942675-layout_revision-38-87x.patch, failed testing. View results

amateescu’s picture

Title: Layout builder should load the latest revision of an entity using the new core API for loading the active revision » Layout builder should use the active variant of an entity
plach’s picture

Status: Reviewed & tested by the community » Needs work

The patch looks good to me, I manually tested it and it indeed fixes the reported issue. However test coverage looks a bit shallow: what about adding a functional test simply checking that the latest revision is loaded on the /node/{node}/layout route when we are dealing with a pending revision? We could create a pending revision manually to avoid having to set up Content Moderation.

+++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php
@@ -74,15 +75,23 @@ class OverridesSectionStorage extends SectionStorageBase implements ContainerFac
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, SectionStorageManagerInterface $section_storage_manager, EntityRepositoryInterface $entity_repository) {

No deprecation/BC layer here: I guess that's fine given that we are in an experimental @internal plugin.

tim.plunkett’s picture

Good idea, I feel much better having a functional test here.

FAIL patch is equivalent to the interdiff

phenaproxima’s picture

+++ b/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php
@@ -119,20 +127,17 @@ public function providerTestExtractIdFromRoute() {
+    $this->entityRepository->getTranslationFromContext(Argument::cetera())->shouldNotBeCalled();

Why wouldn't getTranslationFromContext() be called? Maybe this line should have a comment explaining the train of thought here.

Otherwise, every line in this patch makes crystal clear sense to me.

tim.plunkett’s picture

That check for no calls to getTranslationFromContext was helpful when debugging this, but keeping it in here now is coupling this too closely to knowledge of the internals of EntityRepository. Removed

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, @tim.plunkett! RTBC once Christmas-ey.

The last submitted patch, 54: 2942675-getactive-54-FAIL.patch, failed testing. View results

plach’s picture

Nice spot! That indeed looked suspicious :)

plach’s picture

Saving credits

plach’s picture

Status: Reviewed & tested by the community » Fixed

Committed 17de81c and pushed to 8.7.x. Thanks!

  • plach committed 17de81c on 8.7.x
    Issue #2942675 by tim.plunkett, Sam152, plach, phenaproxima: Layout...
xjm’s picture

Title: Layout builder should use the active variant of an entity » Layout builder should use the active variant of an entity to avoid orphaned revisions

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.