Problem/Motivation

EntityReferenceItem::getValue() will return a target_id property of -1 when the entity has not been saved, however the -1 (NEW_ENTITY_MARKER) is an internal implementation detail. And attempting to set the value with the value returned from getValue will throw an \InvalidArgumentException.
This manifests after serializing and unserializing - so entities with unsaved references cannot be used with things like TempStore or caches., any attempt to get the field values before preSave is called results in an exception.

Steps to reproduce:

  // The term entity is unsaved here.
    $term = entity_create('taxonomy_term', array(
      'name' => $this->randomMachineName(),
      'vid' => $this->term->bundle(),
      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
    ));
    $entity = entity_create('entity_test');
    // Now assign the unsaved term to the field.
    $entity->field_test_taxonomy_term->entity = $term;
    $entity->name->value = $this->randomMachineName();
    // Now save the term.
    $term->save();
    // Get the value.
    $value = $entity->get('field_test_taxonomy_term');
    // Now attempt to set the entity value.
    $entity->field_test_taxonomy_term = $value // Throws an \InvalidArgumentException;

The issue is that EntityReferenceItem::getValue should remove the -1 for target_id

Proposed resolution

Make EntityReferenceItem::getValue handle this more gracefully by removing the static and using a validation constraint to ensure a value is set.

Remaining tasks

Review

User interface changes

None

API changes

EntityReferenceItem::$NEW_MARKER (-1) is removed in favour of a validation constraint

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because broken
Issue priority Major because you should be able to serialize an entity and then unserialize it.
Disruption Removes the protected static so only impacts DER which would be the only thing that sub-classes EntityReferenceItem - both maintainers are active in this issue and are proposing this change to unblock issues there.
CommentFileSizeAuthor
#125 er-set-value-2404331-3.125.patch15.69 KBlarowlan
#125 interdiff.txt2.26 KBlarowlan
#117 er-set-value-2404331-3.again_.patch15.9 KBlarowlan
#117 interdiff.txt1.13 KBlarowlan
#115 er-set-value-2404331-3.reroll.patch15.77 KBlarowlan
#114 er-set-value-2404331-3.114.patch15.77 KBlarowlan
#112 er-set-value-2404331-3.112.patch15.77 KBlarowlan
#109 er-set-value-2404331-3.109.patch15.77 KBlarowlan
#105 er-set-value-2404331-3.105.patch15.7 KBjibran
#105 interdiff.txt2.04 KBjibran
#104 er-set-value-2404331-3.104.patch15.55 KBlarowlan
#104 interdiff.txt6.01 KBlarowlan
#100 er-set-value-2404331-3.10.patch15.73 KBlarowlan
#100 interdiff.txt3.37 KBlarowlan
#99 er-set-value-2404331-3.9.patch15.97 KBlarowlan
#99 interdiff.txt2.38 KBlarowlan
#96 er-set-value-2404331-3.8.patch13.94 KBlarowlan
#96 interdiff.txt773 byteslarowlan
#93 interdiff.txt2.54 KBamateescu
#93 er-set-value-2404331-93.patch14.35 KBamateescu
#92 2404331-92-do-not-test.patch6.65 KBamateescu
#89 er-set-value-2404331-3.6.patch13.85 KBlarowlan
#89 interdiff.txt4.86 KBlarowlan
#85 er-set-value-2404331-3.5.patch12.39 KBlarowlan
#85 interdiff.txt834 byteslarowlan
#83 er-set-value-2404331-3.4.patch12.38 KBlarowlan
#83 interdiff.txt905 byteslarowlan
#81 er-set-value-2404331-3.3.patch11.84 KBlarowlan
#81 interdiff.txt5.4 KBlarowlan
#79 er-set-value-2404331-3.2.patch8.46 KBlarowlan
#74 er-setvalue-2404331-2.74.patch6.42 KBlarowlan
#74 interdiff.txt864 byteslarowlan
#71 er-setvalue-2404331-2.71.patch6.16 KBlarowlan
#66 2404331-66-testEntityAutoCreate-test-only.patch1.91 KBjibran
#66 2404331-66-test-only.patch2.48 KBjibran
#64 er-setvalue-2404331-2.64.patch6.25 KBlarowlan
#64 interdiff.txt693 byteslarowlan
#62 er-setvalue-2404331-2.62.patch6.16 KBlarowlan
#59 er-setvalue-2404331-2.59.patch6.14 KBlarowlan
#57 er-setvalue-2404331-2.57.patch5.26 KBlarowlan
#56 er-setvalue-2404331-2.56.patch5.26 KBlarowlan
#55 er-setvalue-2404331-2.55.patch5.26 KBlarowlan
#53 er-setvalue-2404331-2.infinity+1.patch5.26 KBlarowlan
#49 er-setvalue-2404331-2.49.patch5.23 KBlarowlan
#48 er-setvalue-2404331-2.reroll.patch5.05 KBlarowlan
#40 er-setvalue-2404331-2.40.patch5.05 KBlarowlan
#39 er-setvalue-2404331-2.39.patch5.05 KBlarowlan
#39 interdiff.txt1.03 KBlarowlan
#37 er-setvalue-2404331-2.37.patch4.91 KBlarowlan
#37 interdiff.txt3.33 KBlarowlan
#35 interdiff.txt1.77 KBjibran
#35 er-setvalue-2404331-2.35.patch2.94 KBjibran
#35 er-setvalue-2404331-2.35.test-only.patch2.23 KBjibran
#33 er-setvalue-2404331-2.33.patch1.5 KBjibran
#30 er-setvalue-2404331-2.30.patch1.48 KBlarowlan
#26 er-set-values-updated-added-inline-condition.patch1.51 KBRavindraSingh
#22 er-set-values-updated.patch1.54 KBRavindraSingh
#15 er-setvalue.pass_.patch1.45 KBlarowlan
#15 er-setvalue.fail_.patch794 byteslarowlan
#12 er-setvalue-2404331.pass_.patch1.5 KBlarowlan
#10 er-setvalue-2404331.pass_.patch2.09 KBlarowlan
#8 er-setvalue-2404331.fail_.patch857 byteslarowlan
#6 er-setvalue.fail_.patch904 byteslarowlan
er-setvalue.pass_.patch1.91 KBlarowlan
er-setvalue.fail_.patch875 byteslarowlan
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

larowlan’s picture

Status: Active » Needs review

The last submitted patch, er-setvalue.fail_.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, er-setvalue.pass_.patch, failed testing.

larowlan’s picture

So that test is wrong, back to the drawing board

larowlan’s picture

Assigned: Unassigned » larowlan
larowlan’s picture

Title: EntityReferenceItem target_id can get out of alignment when the reference entity is saved » EntityReferenceItem target_id can get out of alignment when the entity has been serialized and the referenced entity has been saved
Assigned: larowlan » Unassigned
Issue summary: View changes
Status: Needs work » Needs review
FileSize
904 bytes

Here's a failing test

Status: Needs review » Needs work

The last submitted patch, 6: er-setvalue.fail_.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
857 bytes

Status: Needs review » Needs work

The last submitted patch, 8: er-setvalue-2404331.fail_.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
2.09 KB

maybe this?

Status: Needs review » Needs work

The last submitted patch, 10: er-setvalue-2404331.pass_.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
1.5 KB
larowlan’s picture

jibran’s picture

The fix look good to me. I'd suggest to add a comment to the condition.

--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php

--- a/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceItemTest.php

The fix is in core folder and tests are in ER. Which component should we choose? :D

larowlan’s picture

Title: EntityReferenceItem target_id can get out of alignment when the entity has been serialized and the referenced entity has been saved » EntityReferenceItem::getValue() should not return a value for target_id when the target_id is -1
Issue summary: View changes
FileSize
794 bytes
1.45 KB

Actually the issue is that getValue returns the -1. Removing that fixes it.

The last submitted patch, 15: er-setvalue.fail_.patch, failed testing.

larowlan’s picture

larowlan’s picture

Issue summary: View changes
yched’s picture

Assigned: Unassigned » fago

This needs @fago's approval

amateescu’s picture

This is the kind of problems I feared would show up when we were discussing the change to ER's autocreate architecture in Ghent :(

One of the problems with the patch in #15 is what happens if a validation is triggered between "get the field value" and "then set it"? I expect the validation to fail because target_id will be NULL.

I think we need to revisit that decision and try to see if we can bring back the "old way" (e.g. 'target_id' => NULL, 'entity' => $entity_object) for autocreate somehow.

Maybe my proposal to skip validation at some point and bring it back later was not so good, but the real case here is that the 'target_id' property might not pass the NotNull constraint on its own, but it should pass it if combined with the 'entity' property. So we need a way to validate a property with the context of its related properties. Does that make sense?

larowlan’s picture

I don't think we need to 'bring back the old way' - this patch demonstrates the fix.

Note this bug also prevents things like caching of entities with unsaved entity reference fields (as they are serialized which invokes getValue()) and potentially things like the temp-store used for previewing content which I assume also serializes the entity. The internal target_id of -1 is still retained and when setValue is called with just an unsaved entity, the ERItem takes care to ensure the internal target_id is set back to -1 again, so there is no need for the -1 to be exposed outside the ERItem. i.e. internally the -1 remains intact, it's just not leaked outside the ER item

RavindraSingh’s picture

FileSize
1.54 KB

Added the check for if target id values['target_id'] is defined.

larowlan’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -169,6 +169,12 @@ public function getValue($include_computed = FALSE) {
+      if ($this->target_id === static::$NEW_ENTITY_MARKER) {
+        if (isset($values['target_id'])) {

Please combine these into one if, with an && - thanks :)

Thanks for the fix

RavindraSingh’s picture

Issue tags: +#dedelhi
RavindraSingh’s picture

Issue tags: -#dedelhi +#dcdelhi
RavindraSingh’s picture

Added inline condition.

Status: Needs review » Needs work

The last submitted patch, 26: er-set-values-updated-added-inline-condition.patch, failed testing.

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 26: er-set-values-updated-added-inline-condition.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
1.48 KB

possibly manually edited patch?
re-roll with #22 and #23

fago’s picture

hm, that patch meanas $entity->reference->first()->target_id is not the same as $entity->reference->first()->getValue()['target_id'] then - that's unexpected behaviour imo.

Maybe better, we should allow writing the value back in combination with the unsaved entity?

larowlan’s picture

So in that case would $entity->reference->first()->target_id return -1?
Again, that seems like the internal behaviour being leaked.

The root cause of my issue here is TypedDataManager::getPropertyInstance calling setValue with stale field values when unserializing entities from cache.

We do allow writing the values back with the unsaved entity. But as per the test/demo code in issue summary - the issue only happens when the entity is no longer unsaved.

I guess we could make the setValue more permissive, but attempts to do so in #6, #9 and #10 were unsuccessful.

jibran’s picture

amateescu’s picture

@fago, did you see #20? IMO, the solution here is really simple, we just need a custom NotNull constraint for the entity reference item which takes the context into account (i.e. the 'entity' property) when it determines if 'target_id' is NULL or not.

jibran’s picture

The last submitted patch, 35: er-setvalue-2404331-2.35.test-only.patch, failed testing.

larowlan’s picture

Priority: Normal » Major
FileSize
3.33 KB
4.91 KB

So this makes it so that $entity->reference->first()->target_id is the same as $entity->reference->first()->getValue()['target_id'] - ensuring we don't leak the -1 implementation detail.

Internally, EntityReferenceItem needs to use $this->getTargetId() as $this->target_id no longer returns -1 when that is the value.

Bumping this to major given the issues we're seeing in DER with node preview of unsaved entities.

jibran’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -290,4 +290,22 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
+    if ($name == 'target_id' && $value == static::$NEW_ENTITY_MARKER) {
+      return NULL;
+    }

I think we should add comment for this.

larowlan’s picture

sure

larowlan’s picture

Re-roll

RavindraSingh’s picture

Status: Needs review » Reviewed & tested by the community

Awesome, perfactly implemented. moving to RTBC

amateescu’s picture

Status: Reviewed & tested by the community » Needs review

I would still like to hear a definite NO from @fago and/or @yched for the proposal in the last paragraph of #20 / #34, because only @larowlan replied so maybe no one else saw it :)

larowlan’s picture

I agree, would like fago and yched's input and sign off first, left a tell for fago on irc

fago’s picture

Assigned: fago » yched

Thanks. The patch looks solid to me, however I must say I'm not so fond of making the -1 an implementation detail because it requires us to massage incoming/outgoing values all the time. Usually, that's a sign of bad architeture, i.e. if it's not suppoed to be in target_id, don't put it there but e.g. add another internal object property instead.
But as of now, we have to put it there because of validation. I'd agree with amateescu (#20/#34) that fixing validation instead seems to be better option to me, but I'm not sure how realistic or simple that would be. Given that, I'd be fine with moving on with this patch unless someone else can come up with a patch for #20? ;)

But yeah, I'd love to hear yched's and berdir's thoughts on this also. Thus, assigning to the next one.

Status: Needs review » Needs work

The last submitted patch, 40: er-setvalue-2404331-2.40.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
5.05 KB

reroll

larowlan’s picture

re-roll

larowlan’s picture

bump?

Status: Needs review » Needs work

The last submitted patch, 49: er-setvalue-2404331-2.49.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
5.26 KB

reroll

larowlan’s picture

Assigned: yched » Berdir

As per #44

larowlan’s picture

re-roll
Willing to trade for reviews on this.

larowlan’s picture

re-roll
willing to trade for reviews on this

larowlan’s picture

<dejavu>
re-roll
willing to trade for reviews on this
</dejavu>
:)

jibran’s picture

Please have a look at these two points.

  1. Can we explain API change $this->getTargetId() and $this->target_id in IS?
    +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
    @@ -297,6 +301,26 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
    +   * Returns the target id, even if the value is static::$NEW_ENTITY_MARKER.
    

    And maybe explain the difference here as well.

  2. I added the new test in #35 but it didn't fail for ER it should because it failed for DER #2407123: Can't access autocreated entity after serialization . Can you please have a look at it?

From #20

Maybe my proposal to skip validation at some point and bring it back later was not so good, but the real case here is that the 'target_id' property might not pass the NotNull constraint on its own, but it should pass it if combined with the 'entity' property. So we need a way to validate a property with the context of its related properties. Does that make sense?

Can we at least explore that? We can create ERNotNull constraint?

larowlan’s picture

Issue summary: View changes
FileSize
6.14 KB

Fixes 58.1, 58.2 - it looks like the test failed in #35?
Looking at constraint stuff now.
Updated IS

jibran’s picture

larowlan’s picture

trying validation constraint approach here #2334503: Ignore: patch testing issue

larowlan’s picture

Re-roll

Status: Needs review » Needs work

The last submitted patch, 62: er-setvalue-2404331-2.62.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
693 bytes
6.25 KB

Merge use collision

larowlan’s picture

Anyone bold enough to Rtbc this?

jibran’s picture

Just uploading test only patch and testEntityAutoCreate test only patch to make sure fails exists. Other then that this looks RTBC to me.

The last submitted patch, 66: 2404331-66-test-only.patch, failed testing.

jibran’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Which patch is rtbc #64? It's best when the last patch on the issue is the rtbc patch since the rtbc retest uses this one.

Also @Berdir or @yched are yet comment despite people asking for it.

Berdir’s picture

Assigned: Berdir » Unassigned

I can't speak for @yched but I don't feel like being able to provide a useful review for this, I haven't been involved in the recent refactorings that happened around this. @fago, @amateescu and @yched were.. and if they're OK with this then I'm fine with it too ;)

larowlan’s picture

Status: Needs work » Needs review
FileSize
6.16 KB

reroll

larowlan’s picture

Assigned: Unassigned » amateescu

Over to @amateescu as per #70

Status: Needs review » Needs work

The last submitted patch, 71: er-setvalue-2404331-2.71.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
864 bytes
6.42 KB

use statement merge collision

jibran’s picture

+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
@@ -228,6 +227,30 @@ public function testConfigEntityReferenceItem() {
+  public function testEntityAutoCreate() {

@larowlan we talked about updating this test last time around in IRC.

amateescu’s picture

Sorry for the delay, I'm traveling without much internet access until tomorrow evening :/ I'm going to try and poke a bit at the approach of using a custom validation during this long train ride.

daffie’s picture

Just two little nitpicks:

+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
@@ -11,8 +11,8 @@
-use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
 use Drupal\entity_test\Entity\EntityTest;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;

This change is not necessary.

+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceItemTest.php
@@ -228,6 +227,30 @@ public function testConfigEntityReferenceItem() {
+    $entity = serialize($entity);
+    $entity = unserialize($entity);

Can we change this to:

+    $entity_serialized = serialize($entity);
+    $entity = unserialize($entity_serialized);
larowlan’s picture

Here is the custom validation approach, no interdiff - fresh patch

Status: Needs review » Needs work

The last submitted patch, 79: er-set-value-2404331-3.2.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
5.4 KB
11.84 KB

Some fixes

jibran’s picture

New patch doesn't include old changes of testEntitySaveOrder

+  /**
    * Test saving order sequence doesn't matter.
    */
   public function testEntitySaveOrder() {
@@ -243,6 +266,12 @@ public function testEntitySaveOrder() {
     $entity->name->value = $this->randomMachineName();
     // Now save the term.
     $term->save();
+    // Now get the field value.
+    $value = $entity->get('field_test_taxonomy_term');
+    $this->assertTrue(empty($value['target_id']));
+    $this->assertNull($entity->field_test_taxonomy_term->target_id);
+    // And then set it.
+    $entity->field_test_taxonomy_term = $value;
     // And then the entity.
     $entity->save();
     $this->assertEqual($entity->field_test_taxonomy_term->entity->id(), $term->id());
larowlan’s picture

The last submitted patch, 81: er-set-value-2404331-3.3.patch, failed testing.

larowlan’s picture

The last submitted patch, 83: er-set-value-2404331-3.4.patch, failed testing.

jibran’s picture

+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/EntityReferenceNotNullConstraintValidator.php
@@ -0,0 +1,38 @@
+class EntityReferenceNotNullConstraintValidator extends NotNullValidator {

We should also test this.

Status: Needs review » Needs work

The last submitted patch, 85: er-set-value-2404331-3.5.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
4.86 KB
13.85 KB

Adds new test as per #88 and fixes some more fails

larowlan’s picture

Issue summary: View changes

Updated issue summary

jibran’s picture

Title: EntityReferenceItem::getValue() should not return a value for target_id when the target_id is -1 » Remove EntityReferenceItem::$NEW_MARKER (-1) in favour of a validation constraint

Changing the title as well perhaps now @yched will review it. :P

amateescu’s picture

NIce, this looks very similar to my wip patch from London :) It had a few failures locally and it seems that I lost the last commit on my branch, but I'll post it anyway to see if I can spot any major differences.

amateescu’s picture

Assigned: amateescu » Unassigned
FileSize
14.35 KB
2.54 KB

Ok, the only important difference is that we need to bring back the optimization from EntityReferenceFieldItemList::referencedEntities(), which used to check the 'target_id' property first in order to delay loading the computed 'entity' property as much as possible.

Added that optimization and a fixed a few nitpicks in @larowlan's patch (interdiff is to #89), this looks ready to me now.

yched’s picture

Really, really sorry for keeping everyone waiting so long :-(
I'll try to have a closer look in the next few days.

However :

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -89,7 +82,6 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
-    $target_id_definition->setRequired(TRUE);

That was the reason why we introduced the NEW_ENTITY_MARKER in #2232477: Fatal when adding new fields with NOT NULL constraints in a base table that contains existing entities - being able to set the property as "required", so that its SQL column gets a 'NOT NULL' = TRUE and keep the indexes optimized.

If we remove that and abandon the NOT NULL for target_id, then it seems we're basically reverting the e_r part of #2232477: Fatal when adding new fields with NOT NULL constraints in a base table that contains existing entities, and then I'm not sure why we need to add new dedicated validators, they weren't needed back then ?

jibran’s picture

Thank you very much @yched for your insightful reply. :)

We should add explicit tests to make sure that target_id get 'NOT NULL' true. TBH we are not aware of this problem at all and I agree target_id field should be required.

AFAIK we are introducing validator to remove the dirty workaround to this problem (EntityReferenceItem::$NEW_MARKER). Maybe we are addressing this problem on a wrong layer? There should have to be some other way around this.

larowlan’s picture

Adding back the required doesn't seem to break anything, ran a few tests locally - let's see what bot says

Status: Needs review » Needs work

The last submitted patch, 96: er-set-value-2404331-3.8.patch, failed testing.

amateescu’s picture

Heh, it's been so long that even I forgot what my proposal for a fix here was about :/

Looking back through the comments, what we would have to do in the patch is add the custom NotNull constraint to the 'target_id' property, not to the field item, and change SqlContentEntityStorageSchema::getDedicatedTableSchema() to also account for properties that have a 'not null' constraint (or an extension to it) instead of just checking isRequired():

      // A dedicated table only contain rows for actual field values, and no
      // rows for entities where the field is empty. Thus, we can safely
      // enforce 'not null' on the columns for the field's required properties.
      $data_schema['fields'][$real_name]['not null'] = $properties[$column_name]->isRequired();
larowlan’s picture

Status: Needs work » Needs review
FileSize
2.38 KB
15.97 KB

Or we could do this - leave the setRequired but subclass DataDefinition so that we remove the NotNull constraint.
We want the required flag to return true for the column, just not the constraint that operates solely on target_id before preSave has run. This way our custom constraint makes sure that either a new entity or target_id is set and the lack of a target_id doesn't trigger the NotNull constraint from throwing an error. The value is written by the time it hits the DB because of the preSave, but we can bypass validation without the kludgy -1.

We could combine this constraint with ValidReference and remove the new one - but I'm happy with it separate for now - unless someone objects.

larowlan’s picture

Actually, this should be at the EntityReferenceItem level, not the list.

jibran’s picture

Ok so this means ERItem property target_id can be NULL but actual target_id will never be NULL in schema or in theory . If this is correct then we need some documentation for this on ERItem class.

  1. +++ b/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php
    @@ -27,12 +27,12 @@ public function referencedEntities() {
    -      if ($item->hasNewEntity()) {
    -        $target_entities[$delta] = $item->entity;
    -      }
    -      elseif ($item->target_id !== NULL) {
    ...
             $ids[$delta] = $item->target_id;
           }
    +      elseif ($item->hasNewEntity()) {
    +        $target_entities[$delta] = $item->entity;
    +      }
    

    Aren't both the conditions(new one and old one) same? Change seems unwanted.

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
    @@ -33,19 +33,12 @@
    - *   constraints = {"ValidReference" = {}}
    + *   constraints = {"ValidReference" = {}, "EntityReferenceNotNull" = {}}
    

    I like that we have two constraint but NULL ref is a valid ref so perhaps they should belong together.

  3. +++ b/core/lib/Drupal/Core/TypedData/DataReferenceTargetDefinition.php
    @@ -0,0 +1,27 @@
    +class DataReferenceTargetDefinition extends DataDefinition {
    

    Class docs missing.

amateescu’s picture

#101.1: See #93.

jibran’s picture

Thanks @amateescu for clearing that out.
@yched & @fago any thoughts on the current patch.
@larowlan can we use EntityReferenceNotNull in DER if we keep it separate? Or do we need a DynamicEntityReferenceNotNull validator anyway?

larowlan’s picture

@jibran we already have our own ValidReference plugin in DER which we can merge this logic into.

Fixed 101.2, 3 - 101.1 answered by @amateescu

jibran’s picture

Minor fixes.
@larowlan I have uploaded the DER patch in #2407123: Can't access autocreated entity after serialization . DynamicEntityReferenceItemTest::testEntityAutoCreate() and DynamicEntityReferenceItemTest::testEntitySaveOrder() still fails with this patch.

larowlan’s picture

Left a comment over there @jibran.

Status: Needs review » Needs work

The last submitted patch, 105: er-set-value-2404331-3.105.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
15.77 KB
yched’s picture

Hm, smart :-) Haven't done a line-by-line review, but I think I like the approach.

I hate to say that, but... might be good to have @fago vet that too :-/

larowlan’s picture

Assigned: Unassigned » fago

thanks @yched, over to @fago

larowlan’s picture

Another re-roll

jibran’s picture

Let's add a change notice as well or update Field schema no longer uses 'not null' entries.

larowlan’s picture

larowlan’s picture

benjy’s picture

+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
@@ -19,7 +19,12 @@ class ValidReferenceConstraintValidator extends ConstraintValidator {
+    if (!$value->isEmpty() && $value->target_id === NULL && !$value->entity->isNew()) {
+      $this->context->addViolation($constraint->nullMessage);
+      return;
+    }
     if (!isset($value)) {
       return;
     }

If we've just called $value->isEmpty() it doesn't make sense to be checking isset($value) right after?

larowlan’s picture

Fixes #116

Thanks @benjy

larowlan’s picture

Adding issue to the title, as well as the solution

larowlan’s picture

Title: Remove EntityReferenceItem::$NEW_MARKER (-1) in favour of a validation constraint » Can't serialise an entity with an entity reference to an unsaved entity (remove EntityReferenceItem::$NEW_MARKER in favour of a validation constraint)
larowlan’s picture

Issue tags: -#dcdelhi +#dcdelhidcdelhi, +ER check for RC
yched’s picture

Assigned: fago » Unassigned
Status: Needs review » Reviewed & tested by the community

OK, fago isn't responding, so I'm biting the bullet :-)

fago’s picture

Status: Reviewed & tested by the community » Needs work

I really like this approach - good work! :) The patch looks pretty good already also, here some small remarks related to documentation:

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
    @@ -19,10 +19,15 @@ class ValidReferenceConstraintValidator extends ConstraintValidator {
    +    if (!$value->isEmpty() && $value->target_id === NULL && !$value->entity->isNew()) {
    

    Let'S add a pointer here why this is not handled by a regular NotNull constraint. E.g. point to the explanation in the definition class?

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
    @@ -230,10 +227,7 @@ public function onChange($property_name, $notify = TRUE) {
    -    if ($this->target_id !== NULL) {
    -      return FALSE;
    -    }
    -    if ($this->entity && $this->entity instanceof EntityInterface) {
    +    if ($this->target_id !== NULL || (($entity = $this->entity) && $entity instanceof EntityInterface)) {
    

    This seems to change nothing?

fago’s picture

not so "fast" :P

yched’s picture

@fago : HAH ! ;-)

larowlan’s picture

Fixed #122
Thank you @yched and @fago for the reviews.
As promised - I owe you some in return - please ping me on irc/twitter or comment here with any pet issues you need reviewed.

yched’s picture

Status: Needs review » Reviewed & tested by the community

#125 adresses @fago's remarks. Back to RTBC then ?

fago’s picture

yeah, changes look good - agree on RTBC. Thanks!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 125: er-set-value-2404331-3.125.patch, failed testing.

The last submitted patch, 125: er-set-value-2404331-3.125.patch, failed testing.

The last submitted patch, 125: er-set-value-2404331-3.125.patch, failed testing.

larowlan’s picture

Status: Needs work » Reviewed & tested by the community

Random migrate fails

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed ab1885c and pushed to 8.0.x. Thanks!

  • alexpott committed ab1885c on 8.0.x
    Issue #2404331 by larowlan, jibran, amateescu, RavindraSingh: Can't...
jibran’s picture

Thanks @yched, @fago and @amateescu for all the help. @larowlan it is finally fixed great work.

Status: Fixed » Closed (fixed)

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