Problem/Motivation

We discussed this a bit in irc in relation to #2809227: Store revision id in originalRevisionId property to use after revision id is updated and #2833049: ContentEntityBase::hasTranslationChanges will compare a forward revision with the default one instead of the newest forward revision. The big issue is that the revision we should be comparing against depends on context.

1. If you load the default revision, and save it as a new default revision, you should compare the old default and the new default.

2. If you load a non-default revision and save it as a new default revision (reverting, or publishing a draft), you should compare the old default and the new default.

In both cases $entity->original as it is now works for this case.

When saving a non-default revision it gets more complex.

1. No existing forward revision exists, saving a new non-default revision based on the current default. In this case you should compare against the default (which is simultaneously the most recent and the one you loaded)

2. Load and edit an existing forward revision, then save it as a new forward revision with a new workflow state. In this case you should compare against the loaded revision (which is simultaneously the most recent, but not the default).

3. You're reverting a forward revision back to a previous one - i.e. loading revision 1, saving revision 3. In this case the comparison ought to be against revision 2 (which is neither the revision that was loaded nor the default, but it is the most recent)

What this points to is that any one time, there are up to three revisions with different relationships to the one we're about to save:

1. The current default revision
2. The 'source' revision - i.e. the version we loaded as the basis of the one we're saving
3. The revision we're 'replacing' - this could be the default revision but it could also be the revision under consideration in a workflow.

(1,2) (2,3) (1,3), (1,2,3) can always point to the same revision (which we assume in the case with $entity->original)), but they can also all three be different.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

CommentFileSizeAuthor
#10 2833084-10.patch1.92 KBdawehner

Comments

catch created an issue. See original summary.

hchonov’s picture

So before loading $original we need to check through an entity query if there is an existing forward revision or we should add this information to the entity when building/loading it from the storage? We would need this for points 1. and 3..

1. No existing forward revision exists, saving a new non-default revision based on the current default. In this case you should compare against the default (which is simultaneously the most recent and the one you loaded)

if ($entity->wasDefaultRevision()) {$original = $storage->loadUnchanged($entity->id());}
So we need wasDefaultRevision as in this case we would have called $entity->isDefaultRevision(FALSE) and do not know anymore of the current entity was a default revision or not.

2. Load and edit an existing forward revision, then save it as a new forward revision with a new workflow state. In this case you should compare against the loaded revision (which is simultaneously the most recent, but not the default).

$original = $storage->loadRevisionUnchanged($entity->getOriginalRevisionId());
This is blocked on #2809227: Store revision id in originalRevisionId property to use after revision id is updated where we introduce ::getOriginalRevisionId and probably on #2620980: Add static and persistent caching to ContentEntityStorageBase::loadRevision() where we introduce a static cache for entity revisions and ::loadRevisionUnchanged.

3. You're reverting a forward revision back to a previous one - i.e. loading revision 1, saving revision 3. In this case the comparison ought to be against revision 2 (which is neither the revision that was loaded nor the default, but it is the most recent)

What if revision 2 is the default revision? This, I guess, is then Point 1?

$original = $storage->loadRevisionUnchanged($storage->getNewestRevisionId());

jstoller’s picture

Perhaps I'm misunderstanding the problem, but it seems to me that in every case when you save a new revision you are comparing it to the most current revision, whether or not that also happens to be the default revision. Under what circumstances would that not be true?

berdir’s picture

Whenever you want to do someting where only the actually published (=default) revision matters, then when a new default revision is saved you want to compare against the previous default revision to see if you need to do something.

But yes, I suppose in most other cases, you want to compare against the latest revision.

jstoller’s picture

@Birdir: Do you have an example or two of when that might be the case, to help me understand the issue?

berdir’s picture

For example if you integrate with some external service and send data if the value changed, You probably want to do that only if this is the default revision and the it has changed to the previous default revision. A variant of that could be sending out an e-mail if a node is published.. you don't want to send that if it's just the draft that is published.

tstoeckler’s picture

Issue tags: +Triaged core major

We discussed this at the Entity Field API triage meeting with core and Entity API maintainers and we agreed on the current classification as "major".

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

Whenever you want to do someting where only the actually published (=default) revision matters, then when a new default revision is saved you want to compare against the previous default revision to see if you need to do something.

I believe that everyone who cares exactly about that, should explicitly load that revision. In almost all cases we implicit expect the corresponding loaded revisionn, and a lot of code out their doesn't handle that correctly. Yes there might be some problems introduced by changing that, but I believe there are way more problems out there at the moment.

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new1.92 KB

Let's see how many test failures we might have with this.

Status: Needs review » Needs work

The last submitted patch, 10: 2833084-10.patch, failed testing.

hchonov’s picture

@dawehner - some of the test fails might be related to defining original as property - there is an issue for this which has tests fails as well - #2839195: Add a method to access the original property .

timmillwood’s picture

I worry about contrib or custom modules which are depending on the incorrect way $entity->original works. Therefore if we make it work correctly are we breaking backwards compatibility (BC), but then how do we get around this?

Do we deprecate 'original' in D8 and add 'correctOriginal', then deprecate 'correctOriginal' in D9 and add 'original' back.

berdir’s picture

See #2839195: Add a method to access the original property , my suggestion is to add explicit methods for both/all original-y entities that you might want to use.

Version: 8.4.x-dev » 8.5.x-dev

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

plach’s picture

I agree with #14 that the proper fix would be to add methods to explicitly retrieve the original source and default revisions. I'm going to provide a quick fix in #2859042: Impossible to update an entity revision if the field value you are updating matches the default revision., but feel free to close that as a duplicated of this one, if the BC considerations Tim has outlined in #13 wouldn't allow that.

plach’s picture

Issue summary: View changes

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

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

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.

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

catch’s picture

Just committed #2859042: Impossible to update an entity revision if the field value you are updating matches the default revision., we should still add some dedicated methods here to make everything more explicit/documented.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

berdir’s picture

Status: Needs work » Closed (duplicate)