Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
This is a prerequisite to #2937279: [META] Introduce concept of internal resource types.
We need to provide links to related resources to support BC and HATEOAS. However, when resource types may be marked as "internal", those related routes might not be available. Therefore, when we're in the serialization context of the referencing resource type, we need to be able to discover all the resource types to which a field may point and remove those links if all the referenced resource types are internal.
To achieve this, we need to add a discoverability mechanism to ResourceTypes.
Comment | File | Size | Author |
---|---|---|---|
#22 | interdiff-2937961-22.txt | 1.58 KB | gabesullice |
#22 | 2937961-22.patch | 15.35 KB | gabesullice |
|
Comments
Comment #2
e0ipsoComment #3
e0ipso@gabesullice thanks for creating this.
Comment #4
Wim LeersAdding #2937279: [META] Introduce concept of internal resource types.
tag, since the IS says blocksComment #5
gabesulliceI'm still actively working on this.
All tests should pass and all the big ideas are fleshed out. I know of some code standard violations that I still need to fix. Just don't have enough time left today.
Feel free to look at it for architecture, but please save yourself the time and don't yet look for the little things :)
Or wait... that works too!
Comment #6
gabesulliceLOL just kidding! I wish all patches we that easy to review. I totally meant to do that.
Comment #7
e0ipsoKicking off tests and not reviewing until @gabesullice says so.
Comment #8
e0ipsoBack to needs work as per #5.
Comment #9
gabesulliceFails look like testbot problems, let's try again
Comment #10
gabesullice@e0ipso, this is (really) ready for review.
Comment #12
gabesulliceReroll.
Comment #13
Wim LeersWOAH 60K patch!
Most important question before I dive into a review (also because it contributes significantly to the patch size): why introduce an interface? We explicitly removed the interface for
ResourceType
before, because it communicates "you can swap this for your own implementation". It also means we have to commit to that interface, and have to keep supporting it.I do see that you marked it
@deprecated
already. But not@internal
But is it even necessary?
Comment #14
gabesulliceGiven @Wim Leers points about the interface and some chats w/ @e0ipso, I think I need to make a little course adjustment.
Gonna drop the interface and drop the setter injection. That should make this a little smaller in scope.
Back to review soon.
Comment #15
Wim Leers👌
Comment #16
gabesulliceAlright, hopefully this'll cut the patch size (almost) in half and address some of the initial concerns. I'm not sure the interdiff will be all that useful, but including it anyway.
Comment #17
gabesulliceMissed a hunk in the patch
Comment #19
Wim LeersMuch better! Almost 50% smaller patch, nice!
These interfaces are for very different things. I think the latter is the wrong one?
I'd expect the paragraph above the
@return
to be part of the docs under@return
.As a non-native speaker, I wonder if
is the correct adjective here?I instantly think of the second meaning, but it's of course the first meaning. Sounds right.
Why can't we call this automatically?
I'd expect this to just call
getRelateableResourcetTypes()
rather than duplicating some of the logic.Per the above, IMHO this should be
protected
.This feels like a regression.
ResourceType
used to be pure value objects. Now they no longer are, so we need to resort to mocking.This is the consequence of injecting services into
ResourceType
.Have you considered turning a
ResourceTypeRepository
into a factory (or even introducing a separate factory), so that all logic can be contained there, andResourceType
can continue to be a value object?Then we can have a kernel test for the factory, rather than for the value object. All tests that merely consume
ResourceType
value objects could then remain far simpler.It would also keep the codebase easier to reason about.
Comment #20
gabesulliceWhew, I had no idea this issue would end up being such a time sink. I'm not surprised though, the issue of related resource types has eaten up a ton of brain power in every other issue that runs into it (see the FieldResolver). Hopefully this will set us up to solve those issues for good though, so I think it's worth really getting this right :)
I was able to completely revert all the unit test changes and restore most of the ResourceType class to its original form. Now it only has the addition of the three needed methods for the related resource type stuff. Calculating the related resource types has been moved to the repository. AND I think we've cut the patch in half again!
1. Fixed.
2. Done.
3. 👍
4. We can only calculate and set the related resources after all the resource type have been defined. If we were to calculate them when the resource type is first constructed and the resource type has a reference to a not-yet-defined type, then an exception will be thrown as the referenced resource type can't be found.
5. Good call.
6. Moved this into the repository and made it
protected
.7. I tried twice at making a factory and then deleted it again. For the same reasons as number 4 above, it's very hard to avoid a circular dependency where the resource repository relies on the factory and the factory relies on the repository.
Anticipating a question:
While I would have liked to avoid the
setRelatedResourceTypes
call, I can't possibly think of a way to do this so that we don't hit the dependency problem described above. I'm open to suggestions, but given that this is an internal class, I think the \LogicException is probably tolerable.Comment #21
Wim Leers+1 — and think of how much time getting this right (or at least better) will save us once this is in core!
You've been exponentially decreasing the size of the patch … could you do the same with Drupal core please? :P
OMG THIS BECAME 100X SIMPLER, love it now! I have only 3 nits. Then I will RTBC, and will assign to @e0ipso for final review + commit.
Supernit: unnecessary change.
I don't see much additional information in the second sentence here? Can we remove it? Or merge it into the
@return
docs?Should be
protected
— and AFAICT you even meant it to be :)Comment #22
gabesulliceJeeze, I can't get anything past you two.
My first order of business would be to purge all the superfluous newlines.
2. Removed.
3. Eagle eye. Good catch.
Comment #23
Wim LeersComment #24
e0ipsoThis looks good to me. Some clarifications before committing.
Can we ensure that all relationship fields follow this pattern? Probably not. This will work with entity reference (and cousins).
Should we document this contract somehow?
Why this addition?
Comment #25
gabesullice1. That's a really good question and it brings up a deeper point... We really only support entity reference fields and subclasses of it. See the following from
EntityResource.php
:The code in this patch is a little more liberal than that already. Do we ever want to support reference types that aren't descendants of EntityReferenceItem? My guess is that the answer is going to be yes. I just don't know how we should do that without examples of such a field type.
TBH, I think this is really begging for an interface in core that would do a lot of the work in this patch for us. (
$field_definition->getReferenceableEntityTypes()
or something like that. The space is just too unexplored for us to introduce that I think. Questions like, "what about a reference field which isn't constrained by an entity type?" come up. As far as we're concerned, that would be perfectly fine since we've flattened entity type + bundles into "resource types" already.This is a really long winded of saying, maybe the best way to handle this is simply to do nothing and simply wait for the bug report/support request that says "my custom field type isn't handled as a relationship, why?"
2. Simply: "because the test breaks without it". More thoroughly: because
entity_test_with_bundle
has an entity reference fielduser_id
on it (I went down a rabbit hole trying to find our where this comes from with no luck) so that when we calculate the "relatable" resource types, we end up trying to get a definition for 'user' that doesn't exist and breaks the test.Comment #26
Wim LeersYes, the metadata infrastructure for "field that references other entities" is completely missing from core, we can't fix that. The only choice we have is to support
entity_reference
fields, until core provides richer metadata.Comment #27
Wim LeersGiven this is blocking a whole bunch of next steps, and @e0ipso already said in #24:
… implying that this was ready, definitely no major concerns, with just some clarifications desired, which @gabesullice posted in #25, I think it's time to get this in to unblock those next steps.
Comment #29
Wim LeersComment #30
Wim Leers(Commit was delayed because git.drupal.org was down, I could not push!)
Comment #31
e0ipso@gabesullice this one gets me excited! It makes me wonder if the resource type should also be aware of the attributes. Would that make the schema generation for Schemata super simple?
Comment #32
gabesulliceI don't know enough about schemata to answer that, but if it would, I'd be happy to work on that.