We are having a problem where panelized nodes with IPE enabled sporadically become "locked" and can no longer be edited (or more specifically saved). When you try to save (from the node edit tab), you get the error:

The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.

Again, this error occurs when you try to save the node from the "edit" tab (e.g. trying to change the title, author, or workbench state). Oddly, you can still make changes using IPE and save the node using IPE.

This only happens on panelized nodes with IPE enabled, which leads us to strongly suspect that Panelizer and/or IPE are involved.

We don't know how to reproduce this error from scratch or how to "clear" it; once it appears on a node, that node is locked forever. The only workaround right now is to completely abandon the node, and manually duplicate it. Disabling workbench on the content type might also help.

We first saw this issue around the time that we upgraded to Lightning 1.00-rc3, although I doubt it's directly caused by Lightning or this release.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Dane Powell created an issue. See original summary.

Dane Powell’s picture

I have figured out exactly how to reproduce this on a fresh Lightning install... it's an interaction between the IPE tempstore and Workbench. This may seem convoluted, but it's actually very easy for content editors to accidentally do something like this:

  1. Start to add a new page node (or any other content type, as long as it has both IPE and Workbench enabled)
  2. Save the node in Draft state
  3. While viewing the node draft, click "Edit" in the IPE and place any old block on the page
  4. Do NOT click Save in IPE... instead, now click the "Edit" tab above the node. This leaves IPE in an intermediate state, with your latest changes still in the tempstore.
  5. Change the node state to "Published" and save it via the node edit form (not IPE).
  6. Create a new draft of the node, so you regain access to IPE
  7. Notice that you still have a "Save" button available in IPE. Click it and save as custom.
  8. Click the "edit" tab above the node again, and try to save the edit form. You'll now get the error in the issue description.

Notice at this point that the changed time of the latest revision is actually _older_ than that of the published revision, which is what causes this error. In fact, the changed time of the latest revision matches the changed time of the very first draft of the node, where you initially started to use IPE to edit the node.

Maybe IPE just needs to set the "changed" date dynamically when the node is saved, rather than storing this changed time in the tempstore as it seems to currently do?

samuel.mortenson’s picture

I was able to replicate the issue, but not consistently. At any rate, it looks like Entity Types that implement the EntityChangedInterface class require the changed time to be updated before the Entity is saved, which is typically done in the ContentEntityForm. Since Panelizer is updating nodes programmatically, this requirement is never met.

Can we test to see if this patch fixes the issue? If so, we can move the issue to the Panelizer queue.

Dane Powell’s picture

Project: Lightning » Panelizer
Version: 8.x-1.x-dev » 8.x-3.x-dev

Thanks a lot Sam, that patch does seem to prevent nodes from becoming locked (following the testing steps above).

In order to fix existing nodes affected by this bug, after applying the patch you just have to edit and save a locked node once using IPE in order to clear the lock.

Moving to Panelizer queue.

Dane Powell’s picture

Priority: Normal » Major
samuel.mortenson’s picture

Status: Active » Needs review
dsnopek’s picture

+++ b/src/Panelizer.php
@@ -253,6 +254,11 @@ class Panelizer implements PanelizerInterface {
+      if ($entity->getEntityType()->isSubclassOf(EntityChangedInterface::class)) {

Could this be $entity->getEntityType() instanceof EntityChangedInterface instead? That's more inline with the way we usually check this in other Drupal code.

samuel.mortenson’s picture

I based the check on how core was doing it: http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Entity/Conte...

But if instanceof is equivalent, I can change that. From a quick search the only difference I see is this: http://www.java2s.com/Code/Php/Language-Basics/Differencebetweeninstance..., which would never affect this logic.

dsnopek’s picture

Issue tags: +Needs tests

Er, ok, I just looked into this more and it has to be ->isSubclassOf(), sorry!

That method is actually checking if the entity class (not the entity type class itself) is a subclass of the given class/interface. So, I think this is fine!

This would be better with tests, but it sounds like there was trouble reproducing it, so that might not be practical...

DamienMcKenna’s picture

Status: Needs review » Needs work

+1 for needing tests to confirm this bug no longer exists with the patch applied, and tests-only patch that confirms the bug exists.

DamienMcKenna’s picture

Status: Needs work » Fixed
Issue tags: -Needs tests
Parent issue: » #2834847: Plan for Panelizer 8.x-3.0-beta1

After reviewing the issue again, I've decided to commit this, we can work on tests later.

Status: Fixed » Closed (fixed)

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