If a user edits a node (or similar) using Quick Edit, those changes are based on the current DEFAULT revision. That may not be the LATEST revision. If not, then we end up with a new revision in (according to my testing) the default state that is more recent than the previous latest revision. That is, we've forked the forward revisions path. Since we do not track the parentage of forward revisions that means the perviously latest revision is now orphaned and unavailable, except through manually accessing it on the Revisions tab. We also do not support merging, so either way one line or the other is SOL. This is a problem.

One possible solution I discussed with one of our designers, Ashley Cyborski, is that we want to add a "view latest draft" tab anyway. So, enable quick edit on that tab instead and *disable it* on the normal view tab. I do not know how feasible that is. Anyone else know?

Comments

Crell created an issue. See original summary.

Crell’s picture

Crell’s picture

Adding link.

Crell’s picture

dawehner’s picture

Adding that tab is certainly easier than rendering a different revision for a different user, at least for now.

Crell’s picture

How easy is it to change which page has Quick Edit enabled on it? If we have /node/{node}/view and /node/{node}/latest, we want Quick Edit to show up only on the second, not the first, but only when there is a forward revision.

dawehner’s picture

Afaik its possible on every page which have proper rendered fields, so its there automatically.

Crell’s picture

Sure, but we want to *block* Quick Edit on some pages, because you'd be editing the wrong thing.

... And probably in views, too, because those also show the wrong thing. Erf. :-(

dawehner’s picture

Wait, did you just said that quickedit is a problematic concept?

Crell’s picture

I did. :-) If you QuickEdit from the DEFAULT revision, rather than LATEST revision, Bad Things Happen(tm). But the whole point of QuickEdit is to start from the visible revision. So... Erf.

dawehner’s picture

Well, maybe you just made clear that quickedit is a problematic concept for sites with an editorial workflow. Well, I'm sooo sad about that.

Crell’s picture

Sarcastic dawehner is sarcastic...

Still, we'll need a way to disable it. Maybe we can get Wim's input?

Crell’s picture

Project: Moderation State » Workbench Moderation
Version: » 8.x-1.x-dev
wim leers’s picture

The root cause of the problem is not Quick Edit. It is our extremely ill-defined model of revisions.

Quick Edit does only one thing: it allows you to in-place edit the visible fields of an entity. Period. (The visible fields are the non-empty fields.)


The values for fields are determined by which revision of an entity is loaded. And this is where we enter the painful realm wild west of revisions in Drupal (8 or otherwise). The revision that is displayed is indeed the "default" revision. Which revision is the default does not depend on anything: not on time, nor the branch (we don't even have the concept of different branches of an entity), nor the current user, nor anything else.

Now, this is already quite bad. But to make it worse, the handling of does this entity type want a new revision to be created for every edit or not is not implemented in a generic way. In fact, it only exists for Node. So, Quick Edit also had to special-case this:

  protected function init(FormStateInterface $form_state, EntityInterface $entity, $field_name) {
    …
    if ($entity->getEntityTypeId() == 'node') {
      $node_type = $this->nodeTypeStorage->load($entity->bundle());
      $entity->setNewRevision($node_type->isNewRevision());
      $entity->revision_log = NULL;
    }
    …
  }

  protected function buildEntity(array $form, FormStateInterface $form_state) {
    …
    if ($entity->getEntityTypeId() == 'node' && $entity->isNewRevision() && $entity->revision_log->isEmpty()) {
      $entity->revision_log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $entity->get($field_name)->getFieldDefinition()->getLabel()));
    }
    …
  }

And as you can tell, a new revision is created only if NodeType::isNewRevision() returns TRUE, which is the (misnamed) method that Gets whether a new revision should be created by default..

Conclusion: for all entity types except Node, and for Node also if the bundle (NodeType) defaults to "no new revision by default", Quick Edit will just edit the revision you see. Otherwise, it will create a new revision.


The above means that as soon as you have a complex workflow, you need to make sure that you either:

  1. disable in-place editing completely
  2. enhance the revision system to have more metadata, so that you for example know which in-place edits took place while another revision was being moderated, so that those changes can be suggested automatically to be incorporated also. And probably much more.
  3. let Workbench Moderation render the appropriate entity depending on the current user's roles: if the current user is not allowed to moderate, and entity X has revisions in moderation, disable in-place editing for that user for entity X; if the current user is allowed to moderate, render the to-be-moderated revision instead, and add a Currently live tab to allow the moderator to see what is live currently — but also disable in-place editing there.
  4. or some variation on the previous point

Use hook_entity_view_alter() to disable in-place editing for a specific entity by undoing what quickedit_entity_view_alter() did (i.e. unset $build['#attributes']['data-quickedit-entity-id']), and add cacheability metadata if necessary to $build.

Use hook_entity_build_defaults_alter() to change $entity to represent a different revision than the default and again add cacheability metadata if necessary to $build. This one needs double-checking though, not 100% certain about it.

Crell’s picture

Thanks, Wim. Having worked with the revisions API (such as it is) for the last few weeks I completely agree that core is very incomplete here. Hopefully we can improve that in minor releases.

For the time being, we've discussed just disabling Quick Edit entirely for any Moderation-enabled bundle. It sounds from #14 like the best way to do that is via hook_entity_view_alter(), so let's give that a shot and see if that works. Just from a user-expectation standpoint, I think mixing Quick Edit and forward revisions is asking for trouble.

dawehner’s picture

For the time being, we've discussed just disabling Quick Edit entirely for any Moderation-enabled bundle. It sounds from #14 like the best way to do that is via hook_entity_view_alter(), so let's give that a shot and see if that works. Just from a user-expectation standpoint, I think mixing Quick Edit and forward revisions is asking for trouble.

So yeah what about doing that until we find a better solution for it?

wim leers’s picture

Just from a user-expectation standpoint, I think mixing Quick Edit and forward revisions is asking for trouble.

I don't agree with this. However, I do think that a lot of UX work is necessary to make it clear and easy to understand. And I think that solving that is identical to (or at least largely overlapping with, if not a subset of) making Workbench Moderation easy to understand.

I suspect you're working on Workbench Moderation MVP, which means the absolute minimum of making it easy to understand (i.e. across a site, for every piece of content that is being moderated or could be moderated, alther what is shown to make that crystal clear). From that POV, I agree.

moshe weitzman’s picture

For the time being, we've discussed just disabling Quick Edit entirely for any Moderation-enabled bundle.

A less heavy handed approach would be to disable quick edit for any entity that has a forward revision. Not sure how feasible that is.

wim leers’s picture

Should be totally doable.

Crell’s picture

Possibly, but my concern there is that you can quick-edit a node, change the title or whatever, and then after you hit save... seemingly nothing happens, except that quick-edit no longer works. A new revision has been created in Draft, and you could go to the Edit tab to find it, but it's very non-obvious what's happening in that case.

moshe weitzman’s picture

Fair enough ... When an entity has a forward revision, how about changing the pencil to a red pencil (or whatever). The title text would say why quick edit is unavailable. If a person clicks on the red pencil, you can go to the edit form for the forward revision or pop a modal with explanatory text and offer more possible destinations.

Crell’s picture

Maybe, but I have no idea how to do that. :-) Let's try to just disable it first, then we can iterate on better visuals.

dawehner’s picture

StatusFileSize
new1.64 KB

So what about something like this.

wim leers’s picture

Yep, something like that :)

moshe weitzman’s picture

Drupal surgery!

Crell’s picture

Looks about right, but is there no way to do this without module_implements_alter? Generally speaking, module_implements_alter is a sign that you have other problems.

wim leers’s picture

No, module_implements_alter() is just a sign you want to modify the modification another module is making.

This is the biggest weakness of the hook system: it's designed to allow modules to alter things. When >1 module wants to alter the same thing, you end up in this situation: module hook invocation order matters.

If all hook implementations merely add things, there is no problem.

This is how Drupal's hook system is designed to work.

dawehner’s picture

This is the biggest weakness of the hook system: it's designed to allow modules to alter things. When >1 module wants to alter the same thing, you end up in this situation: module hook invocation order matters.

Well, there is no difference from hooks vs. events here. Its more about the general idea of mutability.

On the other hand, the event system is a bit better here. This module_implements_alter() code is basically the same as changing a weight in events, just crazy odd syntax.

Crell’s picture

Status: Active » Needs review
wim leers’s picture

basically the same as changing a weight in events, just crazy odd syntax.

Indeed.

Crell’s picture

Status: Needs review » Needs work
+++ b/workbench_moderation.module
@@ -41,6 +42,30 @@ function workbench_moderation_entity_base_field_info(EntityTypeInterface $entity
+function workbench_moderation_entity_view_alter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
+  /** @var \Drupal\workbench_moderation\ModerationInformationInterface $workbench_moderation_info */
+  $workbench_moderation_info = \Drupal::service('workbench_moderation.moderation_information');
+  if ($entity->getEntityType()->isRevisionable() && !$workbench_moderation_info->isLatestRevision($entity)) {
+    // Hide quickedit, because its super confusing for the user to not edit the
+    // live revision.
+    unset($build['#attributes']['data-quickedit-entity-id']);
+  }
+}
+

Can we move this logic to a service? I'd rather have no hooks in the module that are more than a service call.

Also, the conditional may be simplified to a single method (either in that service or in the info service). There may even be a better method to use already to check that, or we just beef up isLatestRevision to make the isRevisionable() call unnecessary.

Crell’s picture

Issue tags: +Release blocker
dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new4 KB
new4.32 KB

Yeah, I just love your

Status: Needs review » Needs work

The last submitted patch, 33: 2635890-33.patch, failed testing.

The last submitted patch, 33: 2635890-33.patch, failed testing.

The last submitted patch, 33: 2635890-33.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new4 KB
new703 bytes

You should not c&p anything.

Status: Needs review » Needs work

The last submitted patch, 37: 2635890-37.patch, failed testing.

The last submitted patch, 37: 2635890-37.patch, failed testing.

The last submitted patch, 37: 2635890-37.patch, failed testing.

Crell’s picture

Status: Needs work » Needs review

I think the bot hiccuped, so let's try again.

Crell’s picture

Status: Needs review » Needs work

Bot likes it but needs a reroll for the services file. Sorry, I broke it with another commit. :-(

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new3.98 KB

There we go.

Crell’s picture

Status: Needs review » Fixed

Committed. Thanks, dawehner!

  • Crell committed 5cb1801 on 8.x-1.x authored by dawehner
    Issue #2635890 by dawehner: Quick Edit integration
    
wim leers’s picture

+++ b/workbench_moderation.module
@@ -41,6 +42,24 @@ function workbench_moderation_entity_base_field_info(EntityTypeInterface $entity
+  /** @var \Drupal\workbench_moderation\InlineEditingDisabler $inline_editing_disabler */
+  $inline_editing_disabler = \Drupal::service('workbench_moderation.inline_editing_disabler');

+++ b/workbench_moderation.services.yml
@@ -18,6 +18,9 @@ services:
+  workbench_moderation.inline_editing_disabler:
+    class: \Drupal\workbench_moderation\InlineEditingDisabler

It's in-place editing, not
>inline editing.

Status: Fixed » Closed (fixed)

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

The last submitted patch, 23: 2635890-23.patch, failed testing.