Problem/Motivation

Discovered in #2930028-42: Comprehensive JSON API integration test coverage phase 1: for every entity type, individual resources only.

#2543726: Make $term->parent behave like any other entity reference field, to fix REST and Migrate support and de-customize its Views integration added support to core for entity reference fields with null values. JSON API does not support this yet. And consequently, it is not able to properly work with e.g. the $term->parent field yet if it has "root" as the parent.

Proposed resolution

Update JSON API's entity reference field normalizer similarly.

Remaining tasks

Roll a patch

User interface changes

None.

API changes

None.

Data model changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers created an issue. See original summary.

Wim Leers’s picture

Wim Leers’s picture

Assigned: Unassigned » Wim Leers
Wim Leers’s picture

Now really starting this… because this is now also blocking #2945093, per #2945093-53: Comprehensive JSON API integration test coverage phase 3: test JSON API-specific use cases: related/relationship routes, includes and sparse field sets.

Fortunately, there already are some existing test assertions that we'll need to make pass in HEAD. So let's start with those.

Wim Leers’s picture

  1. +++ b/tests/src/Functional/TermTest.php
    @@ -123,9 +123,8 @@ class TermTest extends ResourceTestBase {
           case [0]:
    ...
             $expected_parent_normalization = [
    -          'data' => [],
    +          'data' => NULL,
    

    This one should not be a problem.

  2. +++ b/tests/src/Functional/TermTest.php
    @@ -151,7 +150,7 @@ class TermTest extends ResourceTestBase {
           case [0, 2]:
             $expected_parent_normalization = [
               'data' => [
    -            // @todo This is missing the root parent, fix this in https://www.drupal.org/project/jsonapi/issues/2940339
    +            NULL,
                 [
                   'id' => Term::load(2)->uuid(),
    

    This one could be trickier. Hopefully not!

Wim Leers’s picture

This would be simpler if #2940342: Cacheability metadata on an entity fields' properties is lost had already landed, because that's changing quite a bit wrt normalizing fields, this will most certainly conflict.

Wim Leers’s picture

Status: Needs review » Needs work

There are six cases to support:

  1. Single-cardinality entity reference field, empty (only possible if optional): 'data': null
  2. Single-cardinality entity reference field, non-empty, but has target_id pointing to non-existent entity: 'data': null
  3. Single-cardinality entity reference field, non-empty: 'data': {…}
  4. Multiple-cardinality entity reference field, empty (only possible if optional): 'data': []
  5. Multiple-cardinality entity reference field, non-empty: 'data': [{…}, {…}, {…}]
  6. Multiple-cardinality entity reference field, non-empty, but has >=1 reference with target_id pointing to non-existent entity: 'data': [{…}, null, {…}]

What do we support, and what do we have test coverage for?

More tomorrow.

gabesullice’s picture

Aren't 2 and 6 data integrity issues?

Wim Leers’s picture

No. A top-level Term entity's parent field is explicitly set to 0 (zero) to indicate that its parent is the non-existent "root" Term.

gabesullice’s picture

explicitly set to 0

0 !== NULL and it's not a valid entity ID. Perhaps we should make a special case here for an entity ID === 0 and treat it as if it were the same as case #1.

What about 6?

Wim Leers’s picture

Quoting \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::isEmpty(), which we should respect:

  public function isEmpty() {
    // Avoid loading the entity by first checking the 'target_id'.
    if ($this->target_id !== NULL) {
      return FALSE;
    }
    if ($this->entity && $this->entity instanceof EntityInterface) {
      return FALSE;
    }
    return TRUE;
  }

i.e. any value being set on target_id means it's not empty. For Term entities, it's 0. For others, it could be 'foobar'.

Data integrity is up to the entity type's validation constraints to guarantee. JSON API should not try to interpret it in some way.

Wim Leers’s picture

Two and six are the same thing. In case of e.g. Terms: a term could have both <root> (target_id = 0) and blabla (target_id = 34598) as a its parents. That should then result in

'data': [null,
 {'id': 'some-uuid-here', 'type': 'taxonomy_term--tags'}]
Wim Leers’s picture

Status: Needs work » Needs review
FileSize
658 bytes
1.2 KB

Actually

+++ b/tests/src/Functional/TermTest.php
@@ -123,9 +123,8 @@ class TermTest extends ResourceTestBase {
-          'data' => [],
+          'data' => NULL,

this is wrong!

It should be

'data' => [NULL],

because the JSON API spec says at http://jsonapi.org/format/#document-resource-object-linkage:

Resource linkage MUST be represented as one of the following:

  • null for empty to-one relationships.
  • an empty array ([]) for empty to-many relationships.

and because the parent always is a to-many relationship:

    $fields['parent'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Term Parents'))
      ->setDescription(t('The parents of this term.'))
      ->setSetting('target_type', 'taxonomy_term')
      ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED);

Fixing that expectation. The test will still fail though: HEAD is still broken.

Wim Leers’s picture

FileSize
7.83 KB
9 KB

And this makes TermTest::getIndividual() pass!

However, this sadly causes e.g. the PATCH test coverage to fail. Because that doesn't know how to deal with null values.

That being said, I think that the expectations in #13 are technically violations of JSON API… because it breaks linkage.

But this is how Term entities are designed to work! I'm not sure how to continue here. Thoughts?

Status: Needs review » Needs work

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

Wim Leers’s picture

Status: Needs work » Needs review

Clarifying that this needs feedback.

gabesullice’s picture

<can_of_worms>

This brings me back to my comment in #10.

I think what we need to remember here is that *the purpose of the relationships member is not to serialize entity references.*

The purpose of relationships are to represent links between resources. If the target resource does not exist, there simply cannot be a relationship between a thing and a thing that does not exist, by definition.

Now, it just so happens that the entity reference field is what is immediately available to us to access that information, but I don't believe entity references are a perfect 1:1 mapping to relationships (this difference of understanding is probably related to our conversation in #2949019: Untangle Relationship(Normalizer) and EntityReferenceFieldNormalizer).

Going back to something you said above:

Data integrity is up to the entity type's validation constraints to guarantee. JSON API should not try to interpret it in some way.

I think what I'm getting at is that JSON API is interpreting entity reference values. It's interpreting them as relationships, not attribute values (which is a slightly different thing and imposes different constraints on our interpretation of a data reference).

the parent always is a to-many relationship

This is a little mind-bending. How can a parent by both a child and not child at the same time? This is an impossible state in the current Drupal UI. The only way I can imagine this working is if there were some new concept of distinct hierarchies within a vocabulary (which doesn't exist yet?). Is this ground work for something else?

I think it would be within reason to say that an entity reference field cannot have NULL values. This would be in line with our statement that "we will choose JSON API spec compliance over Drupalisms".


Long story short: I think we need special casing for targeted resources which do not exist. Regardless of whether or not entity reference field values allow it or not.

</can_of_worms>

Wim Leers’s picture

This is a little mind-bending. How can a parent by both a child and not child at the same time

That just meant there can be multiple parents? E.g. chocolate is a child of both food and Belgian specialties.

Long story short: I think we need special casing for targeted resources which do not exist. Regardless of whether or not entity reference field values allow it or not.

That's also what I was leaning towards… thanks for the sanity check!

gabesullice’s picture

Status: Needs review » Needs work

That just meant there can be multiple parents? E.g. "chocolate" is a child of both "food" and "Belgian specialties".

In #7.6, you gave the example of 'data': [{…}, null, {…}], which would indicate that the term was both a root and a child simultaneously, which is what I was confused about. Also, keep that nationalist propaganda to yourself, everyone knows dutch chocolate is the best 😂

That's also what I was leaning towards… thanks for the sanity check!

Don't forget that this leads to a deep, dark rabbit hole where we have to worry about accidentally changing field deltas or not removing null/non-existing references. It's not entirely sane, but it is "the right way to think about it."

Wim Leers’s picture

which would indicate that the term was both a root and a child simultaneously

Indeed, and that's entirely valid/possible!

And in fact, that's exactly my main concern here: if a term has both the root as its parent and a non-root term, then it'd still end up being serialized to 'data': [{…}]. Now it seems the term does NOT have multiple parents, but only a single parent!

So while I agreed with

Long story short: I think we need special casing for targeted resources which do not exist. Regardless of whether or not entity reference field values allow it or not.

… I don't yet know how to do that. The best idea I've had is coming up with a pseudo root term with an all-zero UUID.

gabesullice’s picture

Indeed, and that's entirely valid/possible!

It's only valid/possible internally. And that's why I said, "this is an impossible state in the current Drupal UI." In CS terms it's also an invalid graph—one can't have an edge to a node that doesn't exist.

And in fact, that's exactly my main concern here: if a term has both the root as its parent and a non-root term, then it'd still end up being serialized to 'data': [{…}]. Now it seems the term does NOT have multiple parents, but only a single parent!

Heh, I feel like we're going in circles now :\

The best idea I've had is coming up with a pseudo root term with an all-zero UUID.

This makes me think that I didn't do a good job of explaining my thoughts in #17.

If you do that, you're still "serializing the entity reference field", not representing relationships to resources. There is no relationship to a non-existant term, even a pseudo-term. We shouldn't try to represent it for the sake of matching the storage system.

I think where I'm headed and why I said this was a can of worms is because I think we need to drop PATCH support for relationship routes and keep only POST/DELETE. On GET, we need to elide reference items from relationships when they point to non-existant resources.

When we get a post, we simply add a reference item, when we get a delete, we remove a matching reference item, if it exists. We then don't have to worry about delta or accidentally removing NULL values.

gabesullice’s picture

Additionally, we could also add entity references back to attributes using target_id. Then we could support the full range of possibilities. Of course, then we would need to use a different member name for relationship fields so we didn't have duplicate field names in attributes and relationships (which is forbidden by the spec).

Wim Leers’s picture

In CS terms it's also an invalid graph—one can't have an edge to a node that doesn't exist.

That's not true. It's totally possible to have the root node not exist in memory, and still be able to traverse the tree. It'd just mean special casing that one possible parent. And that's what we did here.

I think we need to drop PATCH support […] On GET, we need to elide reference items from relationships when they point to non-existant resources.

Dropping PATCH support altogether and eliding from GET responses still does not solve the problem: you still won't be able to know whether a term has the root term as a parent. And that's crucial to know.

Additionally, we could also add entity references back to attributes […]

AFAICT that wouldn't work either, because the "related" and "relationships" responses still won't be able to make sense/be consistent with what's in attributes.

gabesullice’s picture

It's totally possible to have the root node not exist in memory, and still be able to traverse the tree.

Hm, that seems a little too clever. I wasn't thinking about it this way. I'll roll with it though.

The best idea I've had is coming up with a pseudo root term with an all-zero UUID.

There's nothing in the spec that requires us to make up a UUID. An ID must just be unique. Perhaps that simplifies things?

Wim Leers’s picture

I'm not sure where you're going with #24 :) Can you elaborate?

gabesullice’s picture

It's totally possible to have the root node not exist in memory, and still be able to traverse the tree.

Hm, that seems a little too clever. I wasn't thinking about it this way. I'll roll with it though.

What I'm trying to say is that GETing from a relationship route is not meant to tell you about field values. It's telling you about linkage. It's about edges. When you DELETE an edge, you should think of it like cutting the link. When there's a NULL target_id, it just doesn't make sense in terms of edges. IOW, you shouldn't be able to add an edge to nothing. IOW, you shouldn't be able to POST NULL.

     ? <- This is the "virtual" root. (A)
    /|
   / O
   | |\
  >| | \  
 | | O  \  <- This edge is valid, but impossible to
 | |/ \  |    create except in custom code (B)
 | O   \ |       
 |      \|       If there's no node on this edge, is it valid graph?
 |       O--- <- NULL seems like a bigger data integrity problem (C)
 |
 This one is doesn't make any sense to me.
 Why would a term ever reference a parent
 *and* a root? (D)

(A) this is what you're describing I think. It's target_id === [root]
(B) this is target_id === [1, 2], you can't ever create this if we're talking about the parent field (this is a totally valid entity reference field otherwise).
(C) this is target_id === [1, NULL], which, as I hope I've shown, may be a valid value for the entity reference field, but not for relationships between nodes. This is what I meant by: "'serializing the entity reference field', not representing relationships to resources."
(D) this is target_id === [1, root]. Again, a valid entity reference value, but if referencing "root" is meant to mean that a term is a root term, then you're saying that the term is both a child and a root. which is very strange. If you go all in on the "virtual" node, it's equivalent to B, which is still impossible to create.

EDIT: just tried this in the UI, apparently both B and D are possible to create (but there might be a bug in the UI). It's still very strange to me, but I guess it's possible nonetheless.

Can you elaborate?

Of course! I just meant that under data we could simply return:

[{"type": "taxonomy_term--foo", "id": "virtual"}] // When target_id === 0

Notably, resource identifiers don't have a links member. Meaning they don't actually have to reference a valid URI, nor do they have to have valid UUID. They simply must "uniquely identify a resource", which in this case, they do, they identify the virtual root of the taxonomy_term--foo tree. It's okay if /jsonapi/taxonomy_term/foo/virtual is 404.

The only concern might be "resource linkage", but the spec says:

Compound documents require “full linkage”, meaning that every included resource MUST be identified by at least one resource identifier object in the same document. These resource identifier objects could either be primary data or represent resource linkage contained within primary or included resources.

Which we may be able to narrowly get away with because the "MUST" is about orphaned resources not orphaned resource identifiers.

It's worth noting that we already have orphaned resource identifiers when they reference a resource to which the user does not have access.


I think the conclusion to take from this is that we can probably map all non-null values to resource identifiers. In the case of <root>, we would make the id "<root>" (the only validity constraint on IDs is that it must be a string, except for client-generated IDs, which SHOULD be valid UUIDs).

This leaves only one remaining concern, can we differentiate between NULL and <root> target IDs?

Wim Leers’s picture

What I'm trying to say is that GETing from a relationship route is not meant to tell you about field values. It's telling you about linkage.

Ah, of course, +1!

Nice ASCII art, although I don't fully grasp it :P Because I don't see how B has target_id === [1, 2]. Doesn't matter though, I can reply to A/B/C/D.

In this A/B/C/D, I think you or I or both of us are mixing up the possible values for target_id (Drupal/database land) with those in the JSON API representation. Only the JSON API representation can contain null!

  • (A) Yes, I'm referring to the virtual "root" (<root> in the UI), which is virtual because no Term entity actually exists in the DB that represents it. It's essentially an unmodifiable, unloadable, unviewable Term.
  • (B) You absolutely can create this, as you later discovered :)
  • (C) I see what you're saying (internal values for an entity reference field may not make sense to represent in JSON API relationships), but I don't think it applies here. I guess I actually don't fully understand what you mean here I think you meant target_id = [1, 0] (Drupal/DB land) maps to relationships = [1, null] (JSON API land)? But if so, that's the same as (D). In your ASCII art, you say there is no node in the graph (hence the NULL?) and are asking whether this then even is a valid graph. The implication being that this cannot occur. I agree, I don't think actually can occur.
  • (D) Same as (B).
[{"type": "taxonomy_term--foo", "id": "virtual"}] // When target_id === 0

😍 I DID NOT REALIZE THIS WAS OKAY! I thought the JSON API spec mandated that every resource identifier's id contained a UUID, but apparently that's not the case! In fact, the JSON API spec only mentions UUIDs in the context of client-generated IDs: http://jsonapi.org/format/#document-resource-identifier-objects.
Cool, this is a great way out!


This leaves only one remaining concern, can we differentiate between NULL and target IDs?

First off: THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU THANK YOU for your deep dive on this, your analysis here was super helpful, super insightful, and obviously unblocks further progress! 🎉 👏 Without you, we wouldn't be at this place where that is the only remaining question :)

Now, to your sole remaining concern!

I'm not yet convinced that a null target ID is in fact possible. See the code I quoted in #11: \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::isEmpty():

  public function isEmpty() {
    // Avoid loading the entity by first checking the 'target_id'.
    if ($this->target_id !== NULL) {
      return FALSE;
    }
    if ($this->entity && $this->entity instanceof EntityInterface) {
      return FALSE;
    }
    return TRUE;
  }

IOW: if it's NULL, then it's empty, and hence entity reference fields can only contain non-NULL values. Zero is an example, but generally it'll be non-zero, because it'll reference entities by non-zero numerical ID.

Wim Leers’s picture

Getting this going again.

The last iteration of this patch is >2.5 months old. Rebased, now retesting, to see how it fares.

gabesullice’s picture

Issue tags: +API-First Initiative
  1. +++ b/src/Normalizer/EntityReferenceFieldNormalizer.php
    @@ -96,13 +96,19 @@ class EntityReferenceFieldNormalizer extends FieldNormalizer implements Denormal
    +      if (!$item->isEmpty() && $item->get('entity')->getValue() === NULL) {
    

    is_null?

  2. +++ b/src/Normalizer/RelationshipNormalizer.php
    @@ -77,12 +78,17 @@ class RelationshipNormalizer extends NormalizerBase {
    +        // If the relationship points to a disabled resource type, do not add the
    

    Nit: 80 line CS

  3. +++ b/src/Normalizer/Value/NullRelationshipItemNormalizerValue.php
    @@ -0,0 +1,35 @@
    + * Helps normalize null relationship items in compliance with the JSON API spec.
    

    How?

  4. +++ b/src/Normalizer/Value/NullRelationshipItemNormalizerValue.php
    @@ -0,0 +1,35 @@
    +    throw new \LogicException('A null relation ship item cannot have a resource.');
    

    s/relation ship/relationship/

  5. +++ b/src/Resource/EntityCollection.php
    @@ -33,11 +36,12 @@ class EntityCollection implements \IteratorAggregate, \Countable {
    +    assert(Inspector::assertAll(function ($entity) { return $entity === NULL || $entity instanceof EntityInterface; }, $entities));
    

    Nit: can this be on 3 lines?

    Also: This is what is failing the tests. That's because entity collections can also receive an EntityAccessDeniedHttpException object.

  6. +++ b/tests/src/Functional/TermTest.php
    @@ -124,9 +124,10 @@ class TermTest extends ResourceTestBase {
    +          'data' => [
    +            NULL,
    +          ],
    

    Do we have tests for NullRelationshipItems in a single-cardinality field?

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
1.07 KB
8.68 KB

#29.5: 🙏 — apparently that changed since #14 from 2.5 months ago!

Only fixing that in this reroll.

Wim Leers’s picture

WOW, I did not expect that!

I was hoping we'd go back from #28's 92 fails to #14's 8 fails.


  • Fixed CS (includes #29.2 + #29.5.
  • #29.1: Why?
  • #29.3: That's just c/p'd from RelationshipItemNormalizerValue + updated.
  • #29.4: Fixed.

Still to do: implement the outcome of the discussion in #17–#27! That includes addressing #29.6.

gabesullice’s picture

#29.1: Why?
#29.3: That's just c/p'd from RelationshipItemNormalizerValue + updated.
#29.4: Fixed.

1. Just a style nit. Take it or leave it :)
3. I don't see the change. By "How?" I just meant, "can you expand this comment?"
4. 👍
6. 👍

Wim Leers’s picture

Assigned: Wim Leers » Unassigned
FileSize
8.43 KB
7.28 KB

I believe this implements #17–#27. This is the goal:

diff --git a/tests/src/Functional/TermTest.php b/tests/src/Functional/TermTest.php
index 61bd003..bddb348 100644
--- a/tests/src/Functional/TermTest.php
+++ b/tests/src/Functional/TermTest.php
@@ -126,7 +126,10 @@ class TermTest extends ResourceTestBase {
       case [0]:
         $expected_parent_normalization = [
           'data' => [
-            NULL,
+            [
+              'id' => 'virtual',
+              'type' => 'taxonomy_term--camelids',
+            ],
           ],
           'links' => [
             'related' => $self_url . '/parent',
@@ -153,7 +156,10 @@ class TermTest extends ResourceTestBase {
       case [0, 2]:
         $expected_parent_normalization = [
           'data' => [
-            NULL,
+            [
+              'id' => 'virtual',
+              'type' => 'taxonomy_term--camelids',
+            ],
             [
               'id' => Term::load(2)->uuid(),
               'type' => 'taxonomy_term--camelids',

Because these "null relationships" or "virtual relationships" now need to generate a proper resource identifier object ({'type':'something','id':'virtual'}) rather than null — as this test expectation diff shows, it no longer makes sense to have a separate normalizer value and normalizer. We just need to update RelationshipItem a bit.

It also makes the diffstat significantly smaller! From

7 files changed, 124 insertions, 17 deletions.

to

4 files changed, 56 insertions, 19 deletions.
gabesullice’s picture

+++ b/tests/src/Functional/TermTest.php
@@ -124,9 +124,13 @@ class TermTest extends ResourceTestBase {
+            [
+              'id' => 'virtual',
+              'type' => 'taxonomy_term--camelids',
+            ],

This is great. I'm so excited that this will finally be handled!

My one remaining concern is that this is going to be very confusing when it's encountered by a developer.

Let's make a change record/documentation for this and then make a follow-up to add a meta member to these resource identifier objects so we end up with:

"data": {
  "id": "virtual",
  "type": "entity_type--bundle",
  "meta": {
    "links": {
      "help": {
        "href": "https://www.drupal.org/link/to/documentation-or-change-record",
        "meta": {
          "about": "Usage and meaning of the 'virtual' resource identifier."
        }
      }
    }
  }
}
gabesullice’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record, +Needs documentation

After we have a CR and docs on d.o, this is RTBC.

gabesullice’s picture

Issue tags: +Needs followup

and followup

Wim Leers’s picture

Assigned: Unassigned » Wim Leers
Issue tags: -Needs followup

Let's make a change record/documentation for this and then make a follow-up to add a meta member to these resource identifier objects so we end up with:

I can do that here.

gabesullice’s picture

Let's make a change record/documentation for this and then make a follow-up to add a meta member to these resource identifier objects so we end up with [a meta member].

I can do that here.

I'm fine with that, but don't forget that entity reference field properties (like alt) get normalized as properties under "meta" too. We'll need to special case the links member so that we don't have (de)normalization problems. I didn't want to hold this up if that turns out to be big deal.

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
1.65 KB
8.63 KB

I thought I was going mad, I couldn't get the green patch at #33 to pass locally! Turns out it was only passing on 8.5, not on 8.6. The 8.6 test I queued confirmed that.

This will make it pass on both branches.

Wim Leers’s picture

Now it should pass on 8.6. The reason that the above patches were only failing on 8.6 is because Drupal 8.6 fixed the parent field. Which is why only on 8.6 the "relationships" routes will work as expected for Term entities.

Also fixed CS violations.

Status: Needs review » Needs work

The last submitted patch, 40: 2940339-41.patch, failed testing. View results

gabesullice’s picture

+++ b/src/Normalizer/EntityReferenceFieldNormalizer.php
@@ -105,7 +105,16 @@ class EntityReferenceFieldNormalizer extends FieldNormalizer implements Denormal
+            'virtual' => [

Why virtual instead of help? I was thinking about https://www.w3.org/TR/html5/links.html#link-type-help, as referenced by https://www.iana.org/assignments/link-relations/link-relations.xhtml

Wim Leers’s picture

Status: Needs work » Needs review
FileSize
2.07 KB
10.58 KB

Oops, that -41 patch should not have been uploaded. It was not ready. Please ignore it. This patch will be relative to #40.

The #40 interdiff fixed Drupal\Tests\jsonapi\Functional\TermTest::testGetRelationships(), but now Drupal\Tests\jsonapi\Functional\TermTest::testRelated() is failing.

(That, and #40 has ::testGetRelationships() still failing on 8.5, because #40 didn't think to only do it for 8.6. Even though I mentioned in the comment for #40 that it had 8.6-only behavior. I forgot to add a hunk.)

This fixes both of those. Was a nightmare to solve!


#42: because help would be the link label/key, and picking something super generic like help prevents us from using this for more generic purposes in the future.

Wim Leers’s picture

WHEW!

Green again at last! Now green on both 8.5 & 8.6!

Now to finally address #34 + #35.

Wim Leers’s picture

Title: Port reference field support for empty/NULL entity reference fields from #2543726 » Port reference field support for non-empty entity reference fields not pointing to an entity from #2543726
Assigned: Wim Leers » Unassigned
Issue tags: -Needs change record, -Needs documentation
FileSize
3.04 KB
12.02 KB

I had accidentally uploaded a patch that implements #34. @gabesullice of course saw this,
and already reviewed it in #42. I gave my rationale in #43, but still looked at the links Gabe provided. One of them said:

Refers to context-sensitive help.

… which of course is what this does. So, did that. Now it's exactly as #34 suggested :)

Also:

  1. Better issue title.
  2. Updated documentation: https://www.drupal.org/docs/8/modules/json-api/core-concepts#virtual — diff: https://www.drupal.org/node/2803133/revisions/view/10926052/10989299
  3. Created change record: https://www.drupal.org/node/2976856
gabesullice’s picture

Status: Needs review » Reviewed & tested by the community

😗👌

  • gabesullice committed 3945727 on 8.x-1.x authored by Wim Leers
    Issue #2940339 by Wim Leers, gabesullice: Port reference field support...

  • gabesullice committed f860f80 on 8.x-2.x authored by Wim Leers
    Issue #2940339 by Wim Leers, gabesullice: Port reference field support...
gabesullice’s picture

Status: Reviewed & tested by the community » Fixed

  • gabesullice committed 93994bb on 8.x-1.x
    Issue #2940339 follow-up by gabesullice: restore test coverage exception...

  • gabesullice committed b0c0f15 on 8.x-2.x
    Issue #2940339 follow-up by gabesullice: restore test coverage exception...
gabesullice’s picture

  • Wim Leers committed e44cfd9 on 8.x-1.x
    Issue #2977879 by Wim Leers, gabesullice: Regression in #2940339: when...
  • Wim Leers committed 94e2778 on 8.x-2.x
    Issue #2977879 by Wim Leers, gabesullice: Regression in #2940339: when...

Status: Fixed » Closed (fixed)

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

rpayanm’s picture

Project: JSON:API » Drupal core
Version: 8.x-1.x-dev » 8.9.x-dev
Component: Code » jsonapi.module

Moving to Drupal core's issue queue.

I'm working on https://www.drupal.org/project/drupal/issues/3122113