Problem/Motivation
In preparation for adding JSON:API to Drupal core, we released the 2.x branch. In it, we tried to clean up many of JSON:API's rough edges. One of which was that while we represented entities as "resource objects" that don't directly match the structure of the underlying entity, when you filtered collections, one would have to filter by entities using their exact structure, even bits that were missing from the resource object representation. We published a change record to this effect.
That change introduced and unintended consequence, anyone filtering by the target_id
property of an entity reference item would have their clients broken. This target_id
property is omitted from resource identifiers because it was believed that it was unnecessary because it sort of duplicated the id
member.
This was a wrong assumption, it may be necessary to filter a the target ID when filtering for an entity referencing a config entity. This might be the case if your client is filtering users by a role machine name, for example.
Proposed resolution
Add a drupal_internal__target_id
property to resource identifiers and make it possible to filter by this value (this ensures that filters still closely match JSON:API's output structure (the purpose of the CR that broke this behavior))
User interface changes
None.
API changes
A new property will be added to JSON:API's output. This is not a breaking change.
Data model changes
None.
Release notes snippet
drupal_internal__target_id has been added to JSON:API responses, see the change record for more information.
Original report
:
I am trying to upgrade my site from the 1.x branch to 2.x but am running in to some confusion and a bit of a performance problem.
When filtering by an entity reference field, I used to be able to do something as simple as /api/entity_type?filter[ref_field]=123, where 123 is the ID of the entity. This is beneficial to using the UUID because it does not require a JOIN on the referenced entity table. The query would be something like:
SELECT base_table.id AS id, base_table.id AS base_table_id FROM {entity_type} WHERE ref_field = 123
Now, when trying to perform the same API request, I get this error: "Invalid nested filtering. The field `ref_field`, given in the path `ref_field` is incomplete, it must end with one of the following specifiers: `id`."
If I change the filter to ?filter[ref_field.id]=123, the query becomes overly complex and performance degrades seriously (we have over 2M entities):
SELECT base_table.id AS id, base_table.id AS base_table_id FROM @entity_type base_table INNER JOIN @entity_type entity_type ON entity_type.id = base_table.id LEFT OUTER JOIN @ref_field ref_field ON ref_field.id = entity_type.ref_field INNER JOIN @ref_field ref_field_2 ON ref_field_2.id = ref_field.id WHERE ref_field_2.uuid LIKE :db_condition_placeholder_0
I am curious: 1) Why was this change added? and 2) Is there anyway I can force the former, more simple approach
Comment | File | Size | Author |
---|---|---|---|
#128 | interdiff-123-128.txt | 1.31 KB | bbrala |
#128 | 3036593-128.patch | 38.38 KB | bbrala |
#123 | 3036593-123.patch | 38.39 KB | effulgentsia |
#118 | interdiff_108_118.txt | 1.93 KB | anmolgoyal74 |
#118 | 3036593-118.patch | 38.38 KB | anmolgoyal74 |
Comments
Comment #2
gabesulliceHi @mstef, I'm pretty sure this report confirms my suspicion in #3034701-5: Filtering users by role.
IOW, I think this is a new regression in the 2.x branch.
I'll let @Wim Leers decide which should be retitled and/or closed as a duplicate.
Thanks for the very detailed bug report!
Comment #3
gabesulliceI'm gonna go ahead and mark the other as a duplicate. This issue summary more closely describes the root cause and doesn't have any back and forth comments from diagnosing the problem.
I think technically we could make this a feature request because the behavior was removed prior to 2.0, but it might be blocking users from updating and it's also forcing users to use a less performant query string.
Comment #4
Wim LeersThanks for the issue management, @gabesullice :)
I posted a proposed solution in #3034701-6: Filtering users by role.
Comment #5
gabesulliceThe proposed solution only deals with targeted config entities, it does not address the performance regression associated with extra
JOINS
when the referenced entity is a content entity (and should be filterable). It's also unclear how it would "match the JSON:API output structure" too.I think we need to add
drupal_internal__target_id
to themeta
member of resource identifiers, then we can acceptfilter[field_entity_reference.meta.drupal_internal__target_id]=42
as a valid filter path, per https://www.drupal.org/node/3015183Comment #6
Wim LeersCorrect.
We'd generate a slightly different query so that on the surface that remains true. But I guess you're saying that config entities are identified by UUID in JSON:API, not their unique name, so we'd still not match the JSON:API output structure?
I like that. It's not pretty, but it's a consequence of JSON:API identifying everything by UUID. It keeps consistency and it makes it clear that you're coupling this to a name that could change (e.g. if a role gets renamed.) rather than a guaranteed-to-never-change UUID.
Comment #7
mstef CreditAttribution: mstef at FFW commentedIs there any update on this now that this module is in core?
Comment #8
e0ipso@mstef I don't think this is currently being looked at.
Comment #9
arefen CreditAttribution: arefen commentedHi e0ipso. I think this feature is very useful.
Are you now any solution to get all user of specific role?
Comment #10
gabesulliceHere's an initial implementation. If someone would be willing to write new tests and update the existing tests for this then this would land much more quickly :)
Setting to Needs Review to get an initial test run. I imagine lots will fail because nothing is expecting the new property to show up under relationship fields.
Comment #11
gabesulliceThat last one will fail code standards. This one should pass.
Comment #13
pixelwhip CreditAttribution: pixelwhip at Aten Design Group commentedI've tried applying this patch as a workaround to the performance issues we've experienced which are described in https://www.drupal.org/project/jsonapi/issues/3022864#comment-13211445.
Filtering by
filter[field_reference.drupal_internal_target_id
does not appear to reduce the amount of INNER_JOINS in the resulting query unless I'm missing something.This is the request URL
And this is the resulting slow query log
Should I expect the extra joins to be there to support the additional WHERE ...status=1 statements?
Comment #14
gabesulliceBumping priority because this regression can:
IIRC, what this issue needs is for someone to write a regression test and to update the existing test expectations to account for the new field.
Comment #15
gabesulliceRerolled against 8.9.x and added a regression test for a possible use case. Leaving the "Needs tests" because I would also like to validate the case of filtering by a target content entity ID, in addition to a config machine name (like this interdiff shows).
Comment #16
gabesulliceHere's a refinement of the regression test I added in #15.
That means that all that is left for this issue is to go through the test failures and update their implementations of
ResourceTestBase::getExpectedDocument()
to include the newdrupal_internal__target_id
property. For the most part, this will just be copy and paste, so I'm removing the "Needs tests" tag since no new tests need to be written.Comment #17
gabesulliceThis should fix the expectations for
Drupal\Tests\jsonapi\Kernel\Context\FieldResolverTest::testResolveInternalEntityQueryPathError
.Comment #18
gabesulliceWhile we're in
FieldResolverTest
, we should probably also test for the non-error case.Comment #20
gabesulliceAdding credit for @bbrala because he helped me with #17 and #18.
Comment #21
bbralaEDIT: Comment #24 had the corrected patch
I've started fixing the tests, fixed the kernel tests and started on the functional tests.
One of the things i found is that
ResourceTestBase::getExpectedGetRelationshipDocumentData()
does not return the correct meta for related resources. This is especially visible in the resources that include user or something similar. I tested some changes to that method inDrupal\Tests\jsonapi\Functional\PathAliasTest::testRelationships
to try and reproduce the correct meta. But whatever i did i ended up overwriting thearity
meta data for the resulting document.I was basing the logic for finding the correct values on the code in
FieldResolver
line 340 and up. But just didn't get it to work. I think i was just looking in the wrong place and couldn't really use my debugger to find out where i needed to be unfortunately.The last testcode i had in
ResourceTestBase::getExpectedGetRelationshipDocumentData()
on line 1755 and up is below. As i said, it was not working, but i'm curious if i was even in the right spot :)Comment #22
bbralaOk, i cannot generate a patch file with PhpStorm appearantly. Used git this time.
Comment #23
bbralaComment #24
bbralaOk, trying one last time hopefully.
Comment #25
bbralaComment #26
bbralaThis patch is not pretty yet, but should fix a load of missing
arity
meta data.Comment #27
bbralaSo most things have been fixed, but the next problem surfaced. It seems there is an issue where the
getPostDocument
method is used for generating the document to POST but also for the document in the response. This seems to trigger errors where theFieldItemNormalizer
tries to make sense of thedrupal_internal__target_id
. This breaks because it is not really a field. It seems we need a way to separate those two so that the normalizer doesnt screw itself.Could you have a look @gabesullice if this is true? Or perhaps it's my changes to the
getExpectedGetRelationshipDocumentData
method, but it doesn't feel that way.Comment #28
bbralaGabe supplied a small patch for the
FieldItemNormalizer
issue. I also deduplicated some of the code to a method.Comment #29
gabesulliceWhat if
target_id
doesn't exist on the field? Will this throw an exception?Elsewhere, we do
$main_property_name = $field_storage_definition->getMainPropertyName()
, then$property_definition = $field_storage_definition->getPropertyDefinition($main_property_name)
.Comment #30
bbralaGood catch! I've updated the implementation to check for existance of the key before using it. Also fixed the last missing
target_id
in one of the tests.Comment #31
bbralaYay green! :)
Comment #32
bbralaComment #33
richgerdesThanks for putting this together. I wanted to help out, but ran out of time to get to this. The patch looks good and works for me.
A few thoughts on review.
target_revision_id
in a addition to thetarget_id
. I'm sure there are other places (the media world for example) where properties are added to references. Should we be iterating over all properties of the fields instead of just the main property? We should be able to do this usinggetPropertyDefinitions()
in place ofgetMainPropertyName()
to get all the definitions. Otherwise$item->propertyDefinitions()
may get us what we need.Otherwise I think everything looks good.
Comment #34
gabesulliceWe discussed #33 a bit during the API-first meeting in Drupal Slack. @richgerdes, I like your suggestion for #33.1, but I think that should be a follow-up. Also, maybe you can open another issue to discuss #33.2? The reason no other properties get the prefix is because the
target_id
field is a weak duplicate of a resource identifier object'sid
member. The only reason you'd want to use it is to exploit some knowledge of internal implementation details to optimize your query or work around the difference between content and config entities. All other properties already exist on under themeta
member, without a prefix and convey unique information.Comment #35
gabesulliceWow, thank you @bbrala! This issue took a lot more grit than I anticipated! Thank you! 🙏
Overall, this looks really good. I only had a few things that I'd like to see fixed. None of them were major, so I went ahead and made the changes myself :)
Leaving as NR for tests, but if they're green, I think this is RTBC.
Here are all the things I addressed:
This is out of date. We filter both by a target config entity and a target content entity.
I also think that this points out that this issue needs an issue summary and title update. We're not really ensuring that
JOIN
s are not added, but only that it's possible to filter by thetarget_id
property, which is useful under certain circumstances.Nit: "a target entity integer ID"
Nit: "—the one authored by..."
I think
$data['meta']
should come after the addition operator because I think we want values in the overriding method to take precedence.I think this can be made simpler by null coalesce (yay, PHP 7!)
null coalesce could help here too.
Also needs spaces after the
if
's so it's notif(
(no space).I believe this will make arity values begin at 1, but arity is indexed from 0.
Finally, in general, I think this section could use some more commentary.
P.S. I'm very impressed by your implementation here. Arity is a weird concept Drupal-ism we invented. There are a ton of ways to naïvely get this implementation wrong. For example, it would have been really easy to misunderstand it as the field item delta or to forget that identifiers without a pair do not receive an arity member. Good job!
I think this could use a comment. The first case is for content entity targets, the second is for config entity targets (which are identified by a machine-name).
Comment #36
gabesulliceWhoops! This shouldn't have been in #35.
Comment #37
bbralaThanks for the review, compliment and fixes. A few small things.
4. Yeah you're absolutely right. It should come after.
5. and 6. Good catch about the
null
coalescing operator, i knew there was a way to get it shorter, but didn't think of that. And yeah, i was relying on PhpStorm for the codestyle. At work we just run fixers for stuff like that, but i couldn't get that to run on core.7. I think you are incorrect. The
++
applies after assigning the value. So it will start at 0 and assign, then increase the value by 1. (And thanks for the compliment ;))8. I didn't know exactly what this represented, so i kept it just a type hint.
Thanks for the help on this, it was fun to do :)
Comment #38
gabesulliceUpdating the IS.
I'm not sure how to phrase the release notes snippet, given that this was introduced before JSON:API was added to Drupal core and prior to the release of 2.x in contrib. Whether it's a bug fix for a regression or a new feature really depends on the lens that you use to evaluate it.
This issue gets Drupal core's JSON:API back to feature-parity with JSON:API 1.x, but it does so in a way that still requires a client to be updated (this is already true when upgrading from 1.x to Drupal core). However, if you're already on Drupal core's JSON:API, this is purely a new feature. Since the release note is for Drupal core, do we consider it a regression if it was was never possible in Drupal core itself; especially if it was unintentionally removed during the 1.x -> 2.x changes?
Comment #39
gabesullicePer my last comment, I'm not sure if this is really a regression.
Comment #40
gabesulliceI had to write a little test script to understand what you said:
What's happening is the the
++
operator doesn't increment$arity_map[$type][$id]
until after the value of$arity_map[$type][$id]
is assigned to$identifier['meta']['arity']
! Which is, ofc, exactly what you said :)I was incorrect. 🤒
Let's do away with the cleverness altogether, whether it's null coalesce or
++
after an assignment :)@bbrala and I discussed and agreed to this interdiff in Slack. RTBC.
Comment #41
Krzysztof Domańskihttps://www.drupal.org/project/drupal/issues/303659 // 404 - Page not found
https://www.drupal.org/project/drupal/issues/3036593 // Here
Comment #42
gabesulliceComment #43
gabesullice@bbrala spotted an encoding error:
this is @bbrala's screenshot. He posted it in Slack
Fixing.
Comment #46
gabesullices/$arity_map/$arity_counter
Comment #48
Wim LeersRe-read this entire issue. Also re-read #3034701: Filtering users by role, which was marked as a duplicate of this.
Issue review
8.x-1.x
, meaning a multiple of that are on8.x-2.x
and only a handful of people have reported running into this, I think it's best to communicate it as a new feature first and foremost. I'd then end with a parenthetical that this did exist by accident in an earlier iteration of the contrib module, and that this should ease the update to core JSON:API.Patch review
🤔👍 It's so confusing that
DataReferenceTargetDefinition
does not implement\Drupal\Core\TypedData\DataReferenceDefinitionInterface
🙃 But that's not this code's fault obviously.I just expected this to live in
isCandidateDefinitionReferenceProperty()
, not inisCandidateDefinitionProperty()
. But like I said, that's Typed Data API forcing us to do this.🥳 AHHHHH! We can finally use this! Because Drupal 8.8 doesn't support PHP 5.5 anymore!
I think this test will become notably easier to understand by specifying a specific role ID, such as
llamallovers
andcatcuddlers
.Right now, the test is still fairly abstract, because it requires knowing that
$role_a
and$role_b
contain meaningful names thatdrupalCreateRole()
happens to generate.The whole point is that we show that it's okay for applications to hardcode certain configuration identifiers, because they are meaningful, and are guaranteed to not change.
Seeing
?filter[roles.meta.drupal_internal__target_id]=llamalovers
will be much easier to understand.👍 This is clearly valuable. Because you would only see a UUID before, and not the meaningful manually chosen ID.
🤔🤔🤔 This feels like we're adding noise in that data. Two kinds of opaque IDs.
I wonder if … we want to only do this for string IDs?
At least initially? We could still add these in the future.
That way, we get to keep our elegance, our minimalist response documents. It seems like a potentially better balance?
🤔 I still don't understand why we're modifying so many test cases instead of keeping them and only adding new ones.
Right now this just screams "I'm proving that this is a BC break", while we want to prove the opposite?
Comment #49
bbralaThanks @wimleers
Yeah, i messed up making that patch. You should look at comment #24 for the correct interdiff and patch. PhpStorm was being unhelpfull.
Comment #50
BryanRice CreditAttribution: BryanRice commentedIn a Similar issue when paragraph items such as links are included as part of the include section, JSONAPI validation fails because links is a reserved word, here is a proposed solution for that.
Comment #51
BryanRice CreditAttribution: BryanRice commentedComment #52
BryanRice CreditAttribution: BryanRice commentedComment #53
BryanRice CreditAttribution: BryanRice commentedComment #54
c7bamford CreditAttribution: c7bamford commented@BryanRice, that seems like a related issue. Maybe you should submit your patch to a new issue to solve that problem.
Comment #56
bbralaI've gone through your feedback and think i've fixed everything.
1. Ok, not much i can do there :)
2. Yay indeed! ;)
3. I've changed the patch so it uses your names. I agree making it readable make things a bit more clear.
4. :)
5. I understand your point in this, that it might seem like noise. One of the things i really like about JSON:API and what i feel is its strength is consistency. I feel this is more consistent and therefor better.
6. You are right. Since only the messages have changed, i've updated the patch so it only changes the exception message. Not sure what i tried to do there.
Comment #57
bbralaComment #59
rajandro CreditAttribution: rajandro as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedThe testbot returns 10 coding standards violations for the current patch. See: https://www.drupal.org/pift-ci-job/1735081
Comment #60
bbralaSorry about that, forgot to run phpcs.
Comment #61
rajandro CreditAttribution: rajandro as a volunteer and at Srijan | A Material+ Company for Drupal India Association commentedThank you Björn Brala, phpcs looks good now.
Comment #63
Wim LeersThe only failure is one in a functional JS test for CKEditor. So: a fail that's most definitely unrelated.
I'm still not sure about #48.5 and #56's response to it. I want to get the thoughts from either @e0ipso or @gabesullice on it, and preferably both. This is going to have a significant impact on the JSON:API DX.
Comment #64
bbralaYeah i totally understand @wimleers, I tried to get this moving again by awnsering your review :)
Comment #65
tanubansal CreditAttribution: tanubansal at Salsa Digital commentedNeed a patch for 9.1
Comment #66
gabesullice#63:
I do not like the proposed solution because it is a perfect or elegant solution. I like it because it is a practical one. There are two reasons to use the
drupal_internal__target_id
field:@Wim Leers, I understand your desire to limit the scope of this change so that our responses contain fewer
drupal_intenal__*
members. They are ugly. But, IMO, that ship sailed when we put in attributes likedrupal_internal__nid
. Limiting to string IDs would be inconsistent not just between different relationship fields, but with attributes likedrupal_internal__nid
. One would wonder: "why is an integer okay here, but not there?"And, less importantly, it would make that optimization I mentioned above impossible.
What would the perfect solution be, if this one isn't the perfect solution? I think we would add to or change the entity reference field's properties to include the target's UUID. There is a related existing issue for something like that: #2874548: Add a choice to use UUID in entity reference values instead of the entity's ID
I'm not confident that issue will ever land the way it is and the opt-in nature would force us to keep this inelegant work-around for some time.
We could create a better issue, titled:
which would be something that wouldn't require opt-in and wouldn't break BC. Doing so would allow JSON:API to filter by that UUID without JOINing against the target entity table.Should we create that issue and postpone this one? IMO, no.
drupal_internal__target_id
on newly created sites.The reason I think we should do it in this order is because I think it will be years before all that work actually gets done, if ever. Our users shouldn't have to wait that long to filter a user by a role.
Comment #67
gabesulliceBack to NR, looks like a testing blip set this issue back to NW.
Comment #68
ebeyrent CreditAttribution: ebeyrent commentedThis is a really important issue for my organization. We use config entities extensively via entity reference fields, and not being able filter our entities by the id of the related config entity means that we can't use jsonapi, we have to build views with REST displays instead, which is not a great solution for us.
What can we do to help move this issue along?
Comment #69
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedWe are running exactly in to this bug when we are trying to filter nodes based on an entity reference to a config entity. This is an important fix, since it's impossible to filter on the values of a referenced config entity normally, which is frustrating since we just need to filter on the target_id stored in the field.
We are trying to apply this patch to 8.9.x and will verify.
Comment #70
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedWe also use (and help maintain) the entity_reference_uuid module, so I'll be interested to see if the target_uuid field value works with this patch.
Comment #71
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedIn terms of the code, I think the change in \Drupal\jsonapi\Context\FieldResolver::isCandidateDefinitionProperty() could be written in a much more readable way with a foreach() loop.
For the change in \Drupal\jsonapi\Normalizer\JsonApiDocumentTopLevelNormalizer::denormalize() it seems like you could just use array_filter() without also needing the array_diff_key()?
Comment #73
bbralaHmm, i've looked into this and i think:
Is equal to:
The question is though, what is faster. Small piece of test code:
Output:
2.668869972229
2.6212129592896
Doesn't matter much, so i guess a function less should be better since it's more readable.
Comment #74
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedYes, I think just inverting the condition to avoid the extra function is what I was thinking. Not really a big deal for performance, just more readable.
Comment #75
bbralaOk i got around to change the 2 parts to something little more readable. I also changed
strpos
tosubstr
since that is quite a lot faster (see http://maettig.com/code/php/php-performance-benchmarks.php).Comment #77
gabesulliceI like these readability improvements. Good call @pwolanin.
Comment #78
gabesulliceTests are failing because this change inverted the logic.
$canonical_ids[]
is supposed to be all IDs whose keys do not begin withdrupal_internal__
. N.b.Comment #79
bbralaYeah noticed it when things started failing. Inverted the change :) Thanks!
Comment #80
bbralaIt purring contently to the end. The test that were failing are not failing anymore, putting it back on needs review :)
Comment #81
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedMinor, but the foreach loop can just iterate over the keys and values?
Also minor, even if the substr() is trivially faster, the strpos() is more readable I think, so I'd favor that.
Comment #82
bbralaAh, good call, overlooked that loop.
Regarding the
substr
i dont really agree. Comparing this way is about 4.5 times faster and not really less readable so i rahter not change that.Comment #84
bbralaFailing test is unrelated, but again a falky Javascript test...
Ckeditor.Drupal\Tests\ckeditor\FunctionalJavascript\CKEditorIntegrationTest
Comment #85
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedSent for retest.
I don't feel strongly about the substr() vs strpos. It would be a little faster/more readable to take the strlen() once outside the array_filter and use the value in the lambda, but as much a style issue as anything.
Also, php micro benchmarks are pretty unreliable and version dependent, so e.g. preferring to use a string function instead of a regex like preg_match() is always true, or making one function call outside a loop instead of inside, but beyond that it's probably in the wash.
Comment #86
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedIn the tests, I don't see why it's using hard-coded numeric IDs.
Should almost certainly be
The absolute value of any numeric IDs in the test setup can differ if the underlying DB has a different autoincrement increment or offset.
Comment #87
bbralaYou are right, there are a few places where we have an actual object to reference.
There is one left that could probably be a real piece of info, but i'm not sure how to get this one:
JsonApiDocumentTopLevelNormalizerTest.php::270
Comment #89
bbralaArg, stupid types.
Comment #90
bbralaComment #92
bbralaFixed it the wrong way around. Oops.
Comment #93
bbralaComment #94
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedComment #95
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedThanks, looks better but it looks like there are still some more places with a hard-code ID, such as
core/modules/jsonapi/tests/src/Kernel/Normalizer/RelationshipNormalizerTest.php
In that one, the fix is not obvious since it's using a data provider. Likely the best quick fix is to actually set the values of the IDs in the setUp() method where the entities are created so that you know they will always have a known, e.g.
(I'm avoiding uid 1 as a best practice since user 1 bypasses all permission checks normally).
Or better, perhaps, create a parallel static variable so the setUp() could look like:
So the test code would be like:
The ID's are also hard-coded in these other test, but that seems to be an existing problem with the way the tests are written, so if you don't feel like fixing those, I think it would be reasonable to create a follow-up issue to address those.
core/modules/jsonapi/tests/src/Functional/TermTest.php
core/modules/jsonapi/tests/src/Functional/CommentTest.php
Comment #96
bbralaYeah, there is a lot of hardcoded stuff around in the tests. I've updated a few files that were changed to something more sane, good pointer to reuse the "logic" for the user uuids. Attached a new patch and interdiff.
Comment #97
bbralaCreated spinoff issue for hardcoded references.
Comment #99
bbralaTypes again.
Comment #100
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedMaybe still need to update RelationshipNormalizerTest.php ti have a static list of expected uids?
Comment #101
bbralaEh, didn't i just do that in my patch?
Comment #102
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedmaybe I clicked the wrong patch file, sorry. Let me re-review.
Comment #103
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedChecking on a local site with entity_reference_uuid module enabled, looks like filtering works as expected with latest patch applied to Drupal 8.9.x:
That module is also exposing the entity ID in meta, but I think that's a bug. #2934458: Mark target_id as a computed field
Trying to filter on that gives a 500 error:
the error:
Comment #104
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedI don't see any outstanding issues in the patch, so I think it's RTBC
Comment #105
gabesulliceThanks for the review @pwolanin!
Comment #106
bbralaThanks @pwolanin! :)
Comment #107
larowlanThis looks good to me, just some uber-nits.
any reason not to use strpos here?
return strpos($key, 'drupal_internal__') !== 0;
slightly easier to read?
feel free to ignore
We don't need an @see to the issue a test was added for, we have git history for those kind of forensics - can you remove this?
the else here is superfluous, we returned early - feel free to ignore
We still need a release note and a change record here, but other than that and the removal of the @see and the take-it-or-leave-it observations above, this looks ready to go
Comment #108
bbralaThanks Lorowlan.
1. Both you and @pwolanin gave this feedback. Guess i'll conform with you guys even though I feel it being suboptimal.
2. That line is not part of this patch, so we could change it, but that should not belong here.
3. You are right, less is more, simplified the control structure there.
Comment #109
pwolanin CreditAttribution: pwolanin as a volunteer and at SciShield commentedIt's still using the substr() to compare the leading string? Again, doesn't matter much, just a harder to read construction.
The other changes look good to further streamline the code.
Comment #111
bbralaMedia_library.Drupal\Tests\media_library\FunctionalJavascript\WidgetUploadTest
failed, unrelated to this issue. Resetting the status to RTBCComment #113
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedLooks like again unrelated test failed: core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
Comment #114
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedComment #117
bbralaThat CK editor test is not fun T_T
Comment #118
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedAdding patch for 9.2.x
Fixed Cspell failed cases and one CS issues.
Comment #119
catchIt's not clear to me why the property has to be drupal_internal_target_id and not target_id. If we were ommitting target_id before, why not add it back as-is? Would be useful if this was in the issue summary and change record, but also an inline comment in the patch somewhere.
Comment #120
gabesulliceHi @catch!
tl;dr: the reason is to be consistent with the field name represented by JSON:API's output.
Longer answer:
We made an early decision in the development of JSON:API to use and standardize on entity UUIDs wherever possible. We found that including entities' serial IDs caused confusion because developers were not sure which ID to use. Therefore we prefixed the serial ID with
drupal_internal
to encourage developers to use the UUID (https://www.drupal.org/node/2984247). Later, we made filtering align with what JSON:API was serializing as well: https://www.drupal.org/node/3015183For example, if one
GET
s a role config entity, the serial ID will be serialized using thedrupal_internal__id
field name. Therefore, it would be strange to have to filter bytarget_id
when the field is externally represented to a consumer asdrupal_internal__id
.IMO, it makes sense to stick with this convention of adding the
drupal_internal__
prefix to any identifiers that are different from the the JSON:APIid
member wherever they appear so that A) filtering remains consistent with output and B) to encourage UUID usage as much as possible.Comment #122
bbralaChanging to RTBC to get a new review with the information provided by gabe. (asked catch on slack about this).
Comment #123
effulgentsia CreditAttribution: effulgentsia at Acquia commentedJust a reroll. No actual changes.
Comment #124
effulgentsia CreditAttribution: effulgentsia at Acquia commentedI'm evaluating this as a feature request, because it's not a regression of anything that was ever in core, and because in HEAD
drupal_internal__target_id
is fully absent in JSON:API output rather than being present and not filterable (correct me if I'm wrong on that).Which in my mind makes this ineligible for 9.2.x. However, it would still be great to get it early into 9.3.x and people who need it in 9.2.x can apply the patch on their site.
Comment #125
effulgentsia CreditAttribution: effulgentsia at Acquia commentedRetitling to my understanding of the issue, but please correct it if I got it wrong.
Comment #126
bbralaSeems reasonable, but changing it to feature is wrong imo. This is a solution to an unintended sideeffect of an earlier change which broken filtering on target_id. This is also mentioned in the initial issue description.
Comment #127
catchComment #128
bbralaQuick little reroll. Nothing of note changed so changing back to RTBC
Comment #129
catchThanks for the re-roll. This still needs a change record and release note before it can be committed - to explain the new property available to developers.
Comment #130
bbralaI'll have a go at the change record.
Comment #131
bbralaChange record available at: https://www.drupal.org/node/3218910.
Comment #132
bbralaUpdated documentation for when it lands in 9.3
Edit: fixed broken link
Comment #134
catchCommitted/pushed to 9.3.x, thanks!
Comment #135
bbralaAwesome!