Problem/Motivation
When viewing the page of an entity which doesn't have a label, the
navigation:title</component> throws the following:
<code>
Drupal\Core\Render\Component\Exception\InvalidComponentDataException: Unable to render component "navigation:title". A render array or a scalar is expected for the slot "content" when using the render element with the "#slots" property in Drupal\Core\Render\Element\ComponentElement->generateComponentTemplate() (line 118 of core/lib/Drupal/Core/Render/Element/ComponentElement.php).
This comes from PageContext which has:
$build += [
[
'#type' => 'component',
'#component' => 'navigation:title',
'#props' => [
'icon' => 'database',
'html_tag' => 'span',
'modifiers' => ['ellipsis', 'xs'],
'extra_classes' => ['top-bar__title'],
],
'#slots' => [
'content' => $entity->label(),
],
],
];
This doesn't account for the fact that EntityInterface::label can legitimately return NULL:
/**
* Gets the label of the entity.
*
* @return string|\Drupal\Core\StringTranslation\TranslatableMarkup|null
* The label of the entity, or NULL if there is no label defined.
*/
public function label();
Steps to reproduce
View an entity without a label entity key/custom label() implementation.
Proposed resolution
Not sure if a slot can validly be defined to allow NULLs, or whether PageContext should perform some checks before attempting to render the component.
Remaining tasks
User interface changes
N/A
Introduced terminology
N/A
API changes
Data model changes
N/A
Release notes snippet
Comments
Comment #2
quietone commentedComment #3
berdirJust cross-referencing things, I did run into the same error, but for me, #3504477: Allow all Renderable values in SDC slots helps because it's a TranslatableMarkup object, not null.
I assume SDC has optional slots, but I think this is a navigation issue. I think an label should either fall back to some fallback string like "- No label -" or possibly skip the whole plugin as it can't really provide meaningful information?
Comment #4
m4oliveiGood find. Tagging as Needs test, it's not obvious how to reproduce it. I was able to reproduce it in a very hacky way by adding the following implementation of
label()to\Drupal\node\Entity\Node, just to illustrate the issue:IMO, the plugin should be skipped if there isn't a useful title or badge. We skip the badge, avoiding this issue if there isn't one. We should do the same for the label.
Comment #6
viappidu commentedFork is a little bit behind...
This patch applies to 11.2.0 (tested)
Comment #7
xmacinfoThe Commerce Invoice module encounters this bug.
Comment #10
xmacinfoMoving to major since this issue essentially blocks displaying content when en entity without label is used.
Comment #11
ivan zugec commentedGetting the same error when I view the logs using the AI logging sub-module with Drupal CMS.
Drupal: 11.2.2
Comment #12
tars16 commentedWe are running into this issue when trying to translate content. The updated check for the label didn't solve our issue, however, casting $label to a string got us past our issue. Not sure if this introduces additional translation issues, but so far it has been working.
Tested with 11.2
Comment #14
plopescAdded new iteration to latest MR including code from #12
Comment #15
tijsdeboeck@plopsec, your MR works perfectly and solved the issue for me.
Comment #17
oily commentedFixing PHPCS in MR !12583 so can run test-only test since the branch contains test coverage.
Need then to choose one branch, merge good code from the other branch and hide it.
Comment #18
oily commentedI wonder if the code
at lines 89 to 93 of PageContext.php in MR !11390 is the best version to date?
Also
at lines 104 to 105?
Comment #19
fjgarlin commentedDisregard comment. Fixing indexing issue.
Comment #20
oily commentedBoth branches now have test coverage.
This one: https://git.drupalcode.org/issue/drupal-3505182/-/tree/3505182-11x-with-... by @Abhijith S includes a full on test entity as in custom content entity. But I cannot trigger the 'test-only' test on it. It tells me I do not have the permissions. Any chance you could trigger it @Abhijith S? And paste the output in a comment?
I tried have added test coverage to the other branch: https://git.drupalcode.org/issue/drupal-3505182/-/tree/3505182-an-entity... using an article node, not a custom content entity, by adding a few lines to an existing text.
But the test is passing. The page is loaded with 200 so no error. And the error text reported in the IS is not appearing on the page inside the test. So again the assertion is passing when it should fail.
Can anyone see why my test is not working? Does an article node not count as an 'entity' in this issue? Does it have to be a 'proper' custom content entity? If so, then the branches could be merged? And see if the test coverage by @Abhijith S does its job?
Comment #21
berdirThe node title is the entity label. You have a label in your test. The title for nodes is required, you can't save a node without one, that's why a test entity type is needed for this.
There doesn't seem to be existing entity in entity_test module that works for this, so adding a new test type is the correct thing to do here.
Comment #22
oily commentedRe: #21 Okay, makes sense. Nice that the entity code has been done and is ready to merge in.
Comment #24
oily commentedI have added the entity test code from one branch to the other and hidden the branch I copied the test entity code from. There is work to do on the tests.
Comment #25
oily commentedCoverted the test entity annotation to an attribute. The pipeline shows broken tests but the output is useful, now. The test entity may need some tweaks but hopefully test coverage is close.
Comment #26
oily commentedThere is a failing assertion in relation to the test entity and the navigation top bar. The assertion fails due to a 403 reponse code instead of 200. Any ideas how to deal with it? Put to Needs review, yet?
Comment #27
berdirYou need a user that is allowed to access that entity. There's an admin permission defined on that test entity.
Comment #28
oily commentedComment #29
oily commentedRe #27 Thank you @berdir. I think I have that right now. That was a lot of 'tweaking' of the test entity. There is an odd error message breaking the test now, the same test as was breaking due to 403. I am not sure if I have fixed the 403. This error may be concealing the 403 one?
Comment #32
oily commentedThis is the test-only output now:
Since the test is breaking due to null value I am wondering if #3 where a fallback value is substituted for null might be best?
Comment #34
plopescCreated a new MR https://git.drupalcode.org/project/drupal/-/merge_requests/13931.
This MR use Unit Tests to double check the different possible combinations for the
navigation:titleandnavigation:badgecomponents.Comment #36
berdirI don't think we need to test render arrays here? \Drupal\Core\Entity\EntityInterface::label() is documented as "string|\Drupal\Core\StringTranslation\TranslatableMarkup|null", an array would break so many existing places.
Comment #37
plopescRemoved support for render arrays. They're ignored now.
Comment #38
berdirThanks.
I would have probably written this as a kernel test, the unit test involves a lot of mocking that in my experience can be tedious to maintain as it's tightly coupled against the implementation, iff we for example change stuff around how the content_moderation integration. But it's there, we can still decide to rewrite this in the future if that's less work than updating it.
Comment #41
catchCommitted/pushed to 11.x and cherry-picked to 11.3.x, thanks!