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.
Problem/Motivation
Drupal\Core\Entity\TypedData\EntityDataDefinition::create()
does not use the definition derived by Drupal\Core\Entity\Plugin\DataType\Deriver\EntityDeriver
.
This causes EntityDataDefinition::getLabel()
to always return NULL
.
This blocks #2936714: Entity type definitions cannot be set as 'internal'.
Proposed resolution
Get the data definition from the typed data manager and use it to instantiate the EntityDataDefinition.
User interface changes
None.
API changes
None.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#23 | interdiff-2936725-21-23.txt | 853 bytes | gabesullice |
#23 | 2936725-23.patch | 5.16 KB | gabesullice |
#18 | 2936725-18.tests_only.patch | 2.82 KB | gabesullice |
Comments
Comment #2
gabesulliceComment #5
gabesulliceThis adds test coverage for bundle-defined labels and fixes the broken Views test.
Comment #6
gabesulliceFix whitespace issues.
Comment #10
gabesulliceFixes the failing test.
Comment #11
Wim LeersCan we get a failing test-only patch?
Isn't this a violation of the interface?
My guess is that it's not, because
\Drupal\Core\Field\TypedData\FieldItemDataDefinition::create()
goes much further still: rather than receiving a string as its parent method\Drupal\Core\TypedData\DataDefinition::create()
dictates, it receives an object, which can contain arbitrary complexity!Oh, and in fact,
\Drupal\Core\Entity\TypedData\EntityDataDefinition::createFromDataType()
already supports this! So::createFromDataType()
supports entity type + bundle, it's just::create()
that doesn't.This is where the updated code does use
\Drupal\Core\Entity\Plugin\DataType\Deriver\EntityDeriver::getDerivativeDefinitions()
, correct?AFAICT these changes are unnecessary?
Comment #12
gabesulliceAbsolutely. Attached the failing and passing patched (no changes since #10)
1. Correct! And because it has
$bundle = NULL
, it can't break existing implementations that don't have the argument. It will just fall right back to the way it worked before.2. Yep.
3. Almost...
Thats needed to avoid undefined indices while also "falling back" to the NULL behavior of
create
. It's entirely possible for either of those$parts
to be missing.Since we already did the
isset
check, isn't it clearer to use the named variables?Comment #13
Wim Leers#12.3: right, I see it now!
Comment #16
BerdirThis might be slightly shorter than the following:
<?php
$data_type = 'entity:' . $entity_type_id;
if ($bundle) {
$data_type .= ':' . $bundle;
}
But I personally find that more readable and I don't like multi-line if/?: statements like that. But not feeling strongly about that.
Also doesn't really need isset() on $entity_type_id/$bundle, it can't be not defined.
entity type is already set in the create() call and we could/should also set bundles there, then this can all go away. Maybe it's already set through $values?
Why does one call return an object and the other an array? doesn't the mock object just get ignored due to the is_array($values) call?
lets use the non-deprecated assertEquals() which expects the expected value first.
Might also be easier to just hardcode the expected label, makes tests easier to read IMHO.
Comment #17
gabesulliceJust setting this back NW so I don't keep forgetting to incorporate @berdir's suggestions.
Comment #18
gabesulliceAll fixed. @Berdir, thanks for all the great suggestions. This is much more readable.
Comment #20
dawehnerThese two comments seems to be a bit pointless, given they describe the code exactly, or is it the code describing the comment ... :) For the first case we could describer rather, why the definition might not exist. In the other cases we could describe that for those cases it doesn't exist, we need to set the entity type explicitly.
Nice!
IMHO it would be nice trying to avoid adding "node" specific test code. What about using
\Drupal\entity_test\Entity\EntityTestWithBundle|\Drupal\entity_test\Entity\EntityTestBundle
instead?Comment #21
gabesulliceThanks for the review @dawehner!
1. I've tried to make these comments a little more informative.
2. Thanks :)
3. I've created a follow-up to avoid expanding the scope of this issue to include rewriting the existing tests for this class here: #2938920: Convert EntityTypeDataTest to use EntityTestWithBundle
Comment #22
gabesulliceAaaand... here's the patch!
Comment #23
gabesulliceSorry for such a sloppy response @dawehner, I was completely distracted. Here's a (hopefully) improved comment WRT to #1.1.
Comment #24
dawehnerThis is really nice!
Comment #25
larowlanif only we could use php7's null coalesce operator and/or splat operator!
Adding review credits
Comment #28
larowlanCommitted b2b7f46 and pushed to 8.6.x.
Cherry-picked as 8525135 and pushed to 8.5.x
Thanks folks
Comment #29
Wim LeersWoot, this means #2936725: EntityDataDefinition::create() does not respect derived entity definitions is unblocked! This also means there's one less blocker for #2932035: ResourceTypes should be internal when EntityType::isInternal is TRUE, which is a blocker for JSON API to get into 8.6.x.
Comment #31
Wim LeersNote that the successor #2936714: Entity type definitions cannot be set as 'internal' also landed, and we're now down to the final core issue: #2941622: Make REST's EntityResource deriver exclude internal entity types and mark ContentModerationState entity type as internal instead of the current hack!
Comment #32
Wim Leers