Problem/Motivation

There might be use cases in custom/contrib where we have to take a different decision depending on if we are comparing a field item list from within ContentEntityStorageBase::hasFieldValueChanged, ContentEntityStorageBase::populateAffectedRevisionTranslations or from within ContentEntityBase::hasTranslationChanges.

ContentEntityStorageBase::hasFieldValueChanged needs to compare only the values that are saved to the storage that would be target_id only in case of entity references.

ContentEntityStorageBase::populateAffectedRevisionTranslations and ContentEntityBase::hasTranslationChanges on the other side might need much more complicated decisions to be made e.g. in our system we have translation changes on a entity reference field if the referenced entities have been changed which we are mainly using for inline editing. In this case FieldItemList::equals is not sufficient because of two reasons:
1. We are not able to differentiate wherefrom the function is called.
2. We do not know the language for which it is called in case of not-translatable field but ContentEntityBase::hasTranslationChanges might still wanna compute differences only for entities of a specific language as when the parent is rendered its references are retrieved in the current language of parent.

Proposed resolution

To solve the problem we introduce a new method FieldItemListInterface::hasTranslationChanges which has two parameters - one for the list to compare against and one for the language to consider. This new method will by default just call ::equals, but to give more developer possibilities the new method will be called to compare the lists from within ContentEntityBase::hasTranslationChanges instead the equals.

Remaining tasks

Review, Change Record, Commit.

User interface changes

None.

API changes

New method FieldItemListInterface::hasTranslationChanges.

Data model changes

None.

Comments

hchonov created an issue. See original summary.

hchonov’s picture

Issue summary: View changes
hchonov’s picture

Issue summary: View changes
hchonov’s picture

Issue summary: View changes
hchonov’s picture

Status: Active » Needs review
StatusFileSize
new2.48 KB
hchonov’s picture

StatusFileSize
new3.28 KB

A new different approach which I think is better. Introduce a new method \Drupal\Core\Field\FieldItemListInterface::hasTranslationChanges which is used by ContentEntityBase::hasTranslationChanges instead the equals method and the new method has also a $langcode parameter in order for it to be able to estimate changes of computed properties based on a specific translation even if the field is not translatable which is needed to populate correctly the revision translation affected flag. The equals method on the other side remains used by the storage to check for direct value changes.

P.S. There will be definitely fails where the field item list is mocked in tests, so after the patch here fails I will take a look where we have to adjust the tests.

hchonov’s picture

Issue tags: +Needs tests
hchonov’s picture

Issue tags: +Needs change record

It needs a change record as well if we go with this approach.

mkalkbrenner’s picture

The patch in #6 would be a great improvement. In Search API we currently re-index all translations if an entity gets saved.
I would love to only re-index the translation that really changed.
The equals method for all fields is not sufficient when it comes to entity references.
Depending on the view mode the "rendered item" that is stored in the index needs to be re-indexed if a referenced entity has a change in the targeted translation.
All this stuff becomes relevant if we think about the various inline entity edit forms.

I'm aware that this might be hard to understand just from the perspective of the current drupal core. The patch just introduces the possibility to overwrite equals() in custom or contrib modules in way that allows a dedicated decision per language.

For our use-case the patch in #6 gave us a big performance improvement.

hchonov’s picture

Title: FieldItemList::equals should be aware if it is called from hasTranslationChanges or from the storage and be able to retrieve the language of the parent entity it is being called for in case of untranslatable field definition » FieldItemList::equals is sufficient from the storage perspective but not from the perspective of ContentEntityBase::hasTranslationChanges
Issue summary: View changes
Issue tags: -Needs tests
StatusFileSize
new5.48 KB
new2.08 KB

Added test that hasTranslationChanges will behave the same as equals currently in core and updated the issue title and summary for the new approach.

tstoeckler’s picture

Very interesting use-case. I think the method makes sense. Would be nice to have an implementation of it in core, but I guess that doesn't really make sense with the core field types.

I think this is another case for the "embedded" flag for entity references introduced in #2824097: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state. With that we could actually implement something like #9 in core if we had that (which would then be a first implementation in core). Although that - together with #9 - brings up an interesting point. In #2824097: Deep serialization for content entities to make an exact snapshot of an entity object's structure based on its current state we have thus far only considered the widget/form side of this, for which serialization is an issue. #9 is now talking about the formatter/view side of this (even though it's not actual Field API formatters (I think?), but still). Not sure yet if that's good (we can re-use the same setting) or bad (the setting is actually not well suited to be on the field-level).

hchonov’s picture

We could implement the method for the core EntityReferenceFieldItemList as it would help a lot in tracking changes when dealing with entity references. We have already implemented the algorithm in our custom field type and we would be happy to share it and probably see it core but I think it would be better if we first make this issue in and then in a follow-up discuss adding a special logic to EntityReferenceFieldItemList.

As currently there is no other real use case but only this one it would not make much sense of providing some artificial tests but the unit ones that we already have.

hchonov’s picture

StatusFileSize
new5.49 KB
new1.64 KB

I was just addressed by mkalkbrenner about the patch and actually there is a small difference between the name and the returned result of the new method. Currently in the patch hasTranslationChanges returns the same as $equals, but actually it should negate the result :).

hchonov’s picture

StatusFileSize
new6.02 KB
new1.28 KB
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -1252,7 +1252,7 @@ public function hasTranslationChanges() {
+        if ($items->hasTranslationChanges($original_items, $this->activeLangcode)) {

I've just realized that we were calling hasTranslationChanges with "x-default" as langcode when iterating over the fields of the default translation instead with the real default langcode.

I've made the change in the new patch version.

Status: Needs review » Needs work

The last submitted patch, 14: 2826021-14.patch, failed testing.

hchonov’s picture

Status: Needs work » Needs review

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.

mkalkbrenner’s picture

StatusFileSize
new1.94 KB
new5.91 KB

re-rolled

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.

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.

james.williams’s picture

I *think* core does have a use-case for this: image fields. See #2941092-3: Add a $properties argument to FieldItemList::equals(). Image fields have height & width properties, which get recomputed on save if they are empty... in which case they can be ignored when checking whether there are translation changes. The approach in this ticket is a million miles better than the nasty patch I supplied to that other ticket as a temporary workaround :-)

catch’s picture

Status: Needs review » Closed (duplicate)

This is an older issue than #2960253: [meta] Allow Paragraphs widget/field and similar use cases to to be considered translatable but that issue has more recent activity, so I'm closing it as duplicate per discussion over there. I've transferred issue credit and hopefully see you over there.

berdir’s picture

Status: Closed (duplicate) » Active

As discussed, I'm reopening this as we agreed on splitting up my issue into 3 separate ones for each change and this is one of those 3.

berdir’s picture

Status: Active » Needs review
StatusFileSize
new10.26 KB
new11.72 KB

This is a combined rebase as well as merging the alternative version from #2960253: [meta] Allow Paragraphs widget/field and similar use cases to to be considered translatable. Specifically, I kept the name we had there (hasAffectingChanges) as plach and I discussed that extensively. I also kept our version where we moved more of the logic into the method (also the ChangedFieldItemList and computed field check).

Instead of checking for $this->activeLangcode vs $this->defaultLangcode, I switched to $this->language()->getId() because that has that logic already included. Means 2 method calls more, though.

Also had to to update the unit test as some additional logic was added to equals() that requires property definitions.

Issue summary is not yet updated.

hchonov’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
    @@ -1428,18 +1427,10 @@ public function hasTranslationChanges() {
    +      if ($items->hasAffectingChanges($original_items, $this->language()->getId())) {
    

    Let's save the language code in a variable outside of the iteration over the fields, so that we reduce the calls for retrieving the language code.

  2. +++ b/core/lib/Drupal/Core/Field/ChangedFieldItemList.php
    @@ -18,4 +18,17 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N
    +    return FALSE;
    
    +++ b/core/lib/Drupal/Core/Field/FieldItemList.php
    @@ -400,4 +400,11 @@ public function equals(FieldItemListInterface $list_to_compare) {
    +    return !$this->getFieldDefinition()->isComputed() && !$this->equals($original_items);
    

    The general approach is to first check that the field isn't computed, which we override and skip in ChangedFieldItemList::hasAffectingChanges(). This makes me think, that probably we don't need the check at all, but we have to implement ComputedItemListTrait::hasAffectingChanges() and return FALSE there while in FieldItemList::hasAffectingChanges() we only delegate the call to FieldItemList::equals(). What do you think?

tstoeckler’s picture

but we have to implement ComputedItemListTrait::hasAffectingChanges() and return FALSE there

No opinion either way, just a quick note that - as @amateescu taught me - because ComputedItemListTrait is agnostic of the field system (i.e. it deals with ItemLists, not FieldItemLists) we should instead create a ComputedFieldItemListBase or so that handles the field-specific logic.

hchonov’s picture

because ComputedItemListTrait is agnostic of the field system (i.e. it deals with ItemLists, not FieldItemLists) we should instead create a ComputedFieldItemListBase or so that handles the field-specific logic.

Hm, but we use the trait in \Drupal\path\Plugin\Field\FieldType\PathFieldItemList and in \Drupal\entity_test\Plugin\Field\ComputedTestFieldItemList, which are FieldItemLists and not ItemLists?

tstoeckler’s picture

Right. My point is that we shouldn't add field-specific logic to the trait itself as it can also be used for (non-field) item lists.

hchonov’s picture

:(

hchonov’s picture

StatusFileSize
new5.77 KB
new14.76 KB

What about keeping track of the non-computed fields in a static property in ContentEntityBase, keyed by the entity type ID and the bundle? This way even when dealing with a lot of entities e.g. nested entity references we'll optimize the saving by having less calls to determine if a field is computed or not and which fields we have to check. We actually already have the function which we could/should use for this - ContentEntityBase::getFieldsToSkipFromTranslationChangesCheck(), where we have to iterate through the fields and retrieve the computed ones as well and exclude them from the fields being checked.

I've implemented this in the attached patch so that it is more clear what I am suggesting.

hchonov’s picture

StatusFileSize
new1.71 KB
new15.15 KB

Fixing #25.1 and the test fails in #30.

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

berdir’s picture

I'm not quite sure how I feel about introducing static properties for that computed check, I doubt that the performance difference of that is measurable. Also, it's not a regression from this patch, we already had the check, the only difference is that it's slightly later, so we do the filter calls already and then decide to ignore the field.

Are we 100% sure that a computed field never wants to affect this? My reason for moving it into the field item class was to support that (maybe just theoretical) use case. A computed field could still be backed by storage, what about the path field, should having an alias on a translatable path field count as translation changes?

plach’s picture

I agree that it would be consistent with the route taken here to allow also computed fields to specify their custom logic around affecting changes, if they really need to.

hchonov’s picture

Re #33:

I'm not quite sure how I feel about introducing static properties for that computed check, I doubt that the performance difference of that is measurable.

Consider saving 30 entities with 10 translations each and 15 fields, 10 of which represent the entity metadata fields. The entities are saved with no changes.

This means that if we check in FieldItemList::hasAffectingChanges() if the field definition is computed, then we'll call 30x10x15 = 4500 times FieldItemList::getFieldDefinition() and through it 4500 times FieldDefinitionInterface::isComputed(). This sums up to 9000 function calls triggered by CEB::hasTranslationChanges() by simply saving the entities without any changes.

During the saving CEB::hasTranslationChanges() is being called for each translation at least 2 times:

  1. ChangedItem::preSave()
  2. ContentEntityStorageBase::populateAffectedRevisionTranslations()

and additionally 2 times from constraint validators:

  1. EntityUntranslatableFieldsConstraintValidator::validate()
  2. ContentTranslationSynchronizedFieldsConstraintValidator::validate()

Which means that the function calls would be not 9000, but at least 2x9000=18 000.

With the solution I suggest we would have only 15 function calls to FieldItemList::getFieldDefinition() and through it 15 function calls to FieldDefinitionInterface::isComputed() per entity type and bundle combination. In the worst case, where the 30 entities are from different entity types each, which kind of architecture I doubt, we would have only 30x(15+15)=900 function calls triggered by CEB::hasTranslationChanges(). Which sums max up to 900 calls no matter how often CEB::hasTranslationChanges() is executed during saving or during the whole runtime.

The difference in the count of function calls between the approaches is 17100 calls.

Function calls in PHP are expensive. Running the following code shows that:

function sum($a, $b) {
  return $a+$b;
};
function test($runs = 17100) {
  $function_call_duration = microtime(TRUE);
  for ($i = 0; $i < $runs; $i++) {
    $c = sum($i, $i+1);
  }
  $function_call_duration = microtime(TRUE) - $function_call_duration;

  $no_function_call_duration = microtime(TRUE);
  for ($i = 0; $i < $runs; $i++) {
    $c = $i + ($i + 1);
  }
  $no_function_call_duration = microtime(TRUE) - $no_function_call_duration;

  echo 'with function call: ', $function_call_duration, "\n";
  echo 'without function call: ', $no_function_call_duration;
}
test();
// with function call: 0,058404207229614
// without function call: 0,00081896781921387

But I don't think, that this is the issue where we have to discuss whether computed fields should or should not have the ability to influence the output of CEB::hasTranslationChanges(). This would be a completely different feature. Currently in CEB::hasTranslationChanges() we skip those fields from the check, therefore I don't see any reason to change this behavior in the current issue. We don't even have an use case for this, so why should we suddenly support it in the current patch when we don't need to?

berdir’s picture

> Function calls in PHP are expensive.

Yes, but it's all relative. Saving an entity does hundreds of method calls :)

This would be a completely different feature. Currently in CEB::hasTranslationChanges() we skip those fields from the check, therefore I don't see any reason to change this behavior in the current issue. We don't even have an use case for this, so why should we suddenly support it in the current patch when we don't need to?

Well, this issue is exactly about making the existing check more flexible. We already renamed the method to hasAffectingChanges() so that it is also not specifically about translations. And I already provided a possible use case above actually, the path field.

Right now in HEAD, I can edit a translation, change nothing except the path field, save it and hasTranslationChanges() return FALSE because the path field is computed. Is that really the expected behavior? Maybe, maybe not, I also don't want to change that behavior here in this issue, but why enforce that such a field can't have a say in what the result of this check is?

hchonov’s picture

Yes, but it's all relative. Saving an entity does hundreds of method calls :)

I don't think this is an argument to introduce thousand more when having the option not to.

Well, this issue is exactly about making the existing check more flexible. We already renamed the method to hasAffectingChanges() so that it is also not specifically about translations. And I already provided a possible use case above actually, the path field.

The main idea of this issue is to enable non-translatable fields like ones holding inline references to be able to hook into the decision of CEB::hasTranslationChanges().

A computed field could still be backed by storage, what about the path field, should having an alias on a translatable path field count as translation changes?

It never did and allowing it might be considered a BC break.

Right now in HEAD, I can edit a translation, change nothing except the path field, save it and hasTranslationChanges() return FALSE because the path field is computed. Is that really the expected behavior? Maybe, maybe not, I also don't want to change that behavior here in this issue, but why enforce that such a field can't have a say in what the result of this check is?

From my point of view this is exactly the right behavior, because this information is stored somewhere else and doesn't affect the content of the entity itself.

I also don't want to change that behavior here in this issue, but why enforce that such a field can't have a say in what the result of this check is?

Because we never needed this feature and still we don't have a real use case for this. All I am asking for is a realistic use case. If there is none, I don't see the point into supporting this feature.

mpp’s picture

Issue summary: View changes
Issue tags: +Contributed project blocker
plach’s picture

In the name of progress, could we drop any non-critical objections we have on each other's code and make sure this lands before alpha? Forcing people to rely on patches for Paragraphs for the whole 8.6 cycle seems a way worse strategy than accumulating some more technical debt, assuming we are doing so.

plach’s picture

berdir’s picture

Priority: Normal » Major

I'll try to get back to this asap.

One thing I noticed is another problem with the usage of this in hasTranslationChanges() or more specifically, the constraint.

We've been testing this in our distribution as part of enabling and using content moderation. We've been running into some problems with more complex field types, problems identified so far:

GeolocationItem: It has a bunch of extra properties that it recalculates in preSave(), but that's only called after validation. I had some success in fixing that by doing that logic in setValue(), or maybe an onChange so that the computed + stored properties are always in sync if you change lat/long. However, it also has a map property that isn't set at all and then the properties don't match. Worked around that by initializing that in setValue() to an empty array, but that's kind of an API change?

WebformEntityReferenceItem: Same deal with a map property.

What seemed to help with the data properties was to put an array_filter() into the callback in FieldItemList::equals(), but not sure if that makes sense? Does seem fine to ignore a property being NULL/''/[] with one that's not set at all, which == fails on?

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.

hchonov’s picture

Re #39:
In that case it makes more sense to stick to the current behaviour, where we're determining in ContentEntityBase which fields to check for differences and leave the discussion about changing this for later.

Re #41:

GeolocationItem: It has a bunch of extra properties that it recalculates in preSave(), but that's only called after validation. I had some success in fixing that by doing that logic in setValue(), or maybe an onChange so that the computed + stored properties are always in sync if you change lat/long. However, it also has a map property that isn't set at all and then the properties don't match. Worked around that by initializing that in setValue() to an empty array, but that's kind of an API change?

WebformEntityReferenceItem: Same deal with a map property.

But this isn't a fault of the current patch, because the equals method would've returned the same, right?

berdir’s picture

> But this isn't a fault of the current patch, because the equals method would've returned the same, right?

No, it is not a fault of the patch. But those examples show that the problem described in the issue title are not yet fully resolved, there is a difference as to when the method is called (before/after preSave()) and also a problem with map properties.

The main difference is the way it is used. For the save part, it's an optimization, if it returns non-equal, we save the values, nothing is broken, it's just slightly slower. However, for this method/validation, it is hard true/false check, either it is OK or it's not, and then you can't save.

I'm not quite sure how to proceed, if we can improve something at all, just wondering if we should keep this issue open and commit the patch we have in yet another related/sub issue?

hchonov’s picture

No, it is not a fault of the patch. But those examples show that the problem described in the issue title are not yet fully resolved, there is a difference as to when the method is called (before/after preSave()) and also a problem with map properties.

The issue problem stated two problems that the current patch is solving:

1. We are not able to differentiate wherefrom the function is called.
2. We do not know the language for which it is called in case of not-translatable field but ContentEntityBase::hasTranslationChanges might still wanna compute differences only for entities of a specific language as when the parent is rendered its references are retrieved in the current language of parent.

Both problems are solved by the patch. If you think we have to change the issue title to better fit the goal of the issue, then we might.

We have a similar case where we're changing values in a field preSave method, but we've added a special behavior to the new field method for detecting this. This is what the new method is there for, not simply to forward the call to the equals method :).

IMHO the problems you've described should be solved in the GeolocationItem and the current patch is ready to go.

james.williams’s picture

Title: FieldItemList::equals is sufficient from the storage perspective but not from the perspective of ContentEntityBase::hasTranslationChanges » FieldItemList::equals is sufficient from the storage perspective but not for code checking for changes

IMHO the problems you've described should be solved in the GeolocationItem and the current patch is ready to go.

I totally agree with this, in the sense that typed data item classes should be able to do what they like with their own data structures, so they then need a way to indicate how a data structure is to be considered 'changed' or not.

Note that core's own ImageItem also needs something implemented for this, as its 'height' and 'width' properties have the same kinds of issues as the contrib GeolocationItem, i.e. they are filled in by its preSave() method, when needed. I suspect follow-up issues are best for item classes though anyway, no need to delay improving the core API / field processing.

I trust my change to the issue title helpfully reflects where this discussion/work has now progressed. I.e. there are multiple places that check for changes, translation is just one of them.

hchonov’s picture

The ImageItem is a good example, but actually its preSave would change the width and height properties only if the referenced image entity has been changed. So in this case the equals method is able to determine that there are changes before the preSave method has run. We don't need the information which properties have changed. We only need to know if there is a change on the item and this works currently. If a change on property A triggers a change on property B in the field item preSave method, then we still have the needed information for the equals method, no matter if it runs before or after the preSave.. With the GeolocationItem its probably the same story.

james.williams’s picture

We only need to know if there is a change on the item and this works currently.

Unfortunately it's not quite that simple. The widget used for images can end up submitting with no change in the referenced image, but clearing the height & width. So currently that's then considered a change, even though the preSave would only go and set the height & width properties what they already are in storage. ie. something like the following are compared:

array(
  'file reference' => 'fid123',
  'height' => NULL,
  'width' => NULL,
  'alt' => 'no change',
)

vs

array(
  'file reference' => 'fid123',
  'height' => '456',
  'width' => '789',
  'alt' => 'no change',
)

Those are not considered equal, even though the height & width in the first array will get set to '456' and '789' by preSave. I hope that makes sense?

So yes the new patch would enable resolving this, because the ImageItem class could implement the new method to check for equality by ignoring the empty dimension properties. So I'm saying that I'm in favour of your patch, and just that we have a potential test case in core :-)

berdir’s picture

@plach and I discussed how to move forward with this exactly.

ImageItem is in fact a good example of the problem that I described. That said, this isn't a problem we can solve generically I think, best we can do is change existing field type plugins to e.g. recalculate those values on setValue() and not preSave(), so they're always in sync.

However, that is a pre-existing problem with the equals() implementation, how it is used and when it is called. While the issue title is quite generic, the goal/implementation is actually specifically to allow field types to implement and additional, new method to react differently to storage-level equals() checks compared to checks that are about whether it has (translation) affecting changes.

Considering that, and that this is something that can not get into a stable minor release and is basically ready, we think it makes more sense to create a new issue for making sure that all field types need to be adjusted for equals to work as expected here. That is also something that should be possible in a patch release I think.

In that light, I'm also not quite sure about the issue title change.

While @hchonov and I still disagree about some details of the patch and whether they are necessary here, I think this is good enough as a first step and solve both his problem as well as mine. If there is ever a problem with that static cache, we can change it internally for example.

plach’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record

Thanks @Berdir, RTBC'ing per #49.

Also removing the needs CR tag, since we have https://www.drupal.org/node/2975280 now.

james.williams’s picture

Hooray, thanks everyone!! :-D

hchonov’s picture

While @hchonov and I still disagree about some details of the patch and
whether they are necessary here, I think this is good enough as a first step
and solve both his problem as well as mine. If there is ever a problem with
that static cache, we can change it internally for example.

@Berdir++, at least we agree on the basic approach, which is something :).

wim leers’s picture

🎉

catch’s picture

+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -176,6 +175,13 @@
 
+  /**
+   * Local cache for fields to skip from the checking for translation changes.
+   *
+   * @var array
+   */
+  protected static $fieldsToSkipFromTranslationChangesCheck = [];
+

This could do with an explanation of why it has to be a static property, from the discussion here it appears to be only for performance?

  • catch committed d2f461f on 8.7.x
    Issue #2826021 by hchonov, Berdir, mkalkbrenner, plach, james.williams,...

  • catch committed 6aae1b8 on 8.6.x
    Issue #2826021 by hchonov, Berdir, mkalkbrenner, plach, james.williams,...
catch’s picture

Version: 8.7.x-dev » 8.6.x-dev
Status: Reviewed & tested by the community » Fixed

I've opened #2988300: Should ContentEntityBase::fieldsToSkipFromTranslationChangesCheck be static? as a follow-up.

Committed/pushed to 8.7.x and cherry-picked to 8.6.x. Thanks!

berdir’s picture

Awesome, thanks!

I also created #2988309: Ensure that all field types return TRUE on equals() for the same values to deal with the image field problem mentioned in #48 as well as the contrib field types I mentioned in #41.

Status: Fixed » Closed (fixed)

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