Problem/Motivation
EntityViewBuilder::getSingleFieldDisplay() relies on creating a fake non-sectioned display and setting values on it for rendering.
EntityViewDisplay::setComponent() is called during rendering, while the Layout Builder BC layer for ::setComponent() calls assumes it is called during configuration changes only (in install/update, or when adding new fields).
To avoid recursion, a check for the magic view mode \Drupal\Core\Entity\EntityDisplayBase::CUSTOM_MODE
was added.
However, after #2936358: Layout Builder should be opt-in per display (entity type/bundle/view mode) there is now a check for whether LB is enabled for that display.
Since it can never be enabled for that magic view mode, the extra check is redundant.
Proposed resolution
Remove the @todo and the check for CUSTOM_MODE
Remaining tasks
N/A
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Comment | File | Size | Author |
---|---|---|---|
#9 | 2936464-9.patch | 894 bytes | phenaproxima |
#7 | interdiff-2936464-4-7.txt | 1.06 KB | phenaproxima |
#7 | 2936464-7.patch | 10.51 KB | phenaproxima |
#4 | 2936464-4.patch | 10.33 KB | phenaproxima |
Comments
Comment #2
tim.plunkettComment #3
phenaproximaAs described in #2976148-21: Layout-based entity rendering should delegate to the correct section storage instead of hardcoding to either defaults or overrides, fixing this issue may further mitigate the possibility of infinite recursive rendering.
Comment #4
phenaproximaHere's one possibility: move the business logic of rendering field items into EntityViewBuilder, rather than EntityViewDisplay, then have EntityViewDisplay delegate to that. This allows us to completely remove getSingleFieldDisplay(). No tests yet -- I'd like this idea validated first, and I want to see how many tests this breaks.
Comment #7
phenaproximaThis oughta fix at least one failure.
Comment #9
phenaproximaDiscussed with @tim.plunkett in Slack. We realized that this approach will not work, because:
All that said, here's a new patch which removes the workaround. Another todo bites the dust!
Comment #10
tim.plunkettI concur!
Comment #11
alexpottI think the issue summary needs an update to add why #9 is the correct approach. I might be missing something but the comment in #9 doesn't really explain it to me. It would be good to know what test was originally breaking that caused us to add the work around and if it is possible by clicking around in the UI to cause the recursive rendering.
Comment #12
tim.plunkettRewrote the IS. A longer explanation is below.
EntityViewDisplay::setComponent() is used to configure the field formatter for a given field.
Layout Builder swaps out the EntityViewDisplay entity class for it's own, and overrides setComponent().
It does this to add a new field block corresponding to the given field.
For example, when you add a new body field to a content type, node_add_body_field() calls setComponent() which adds a field block for the body field. This way newly added fields are immediately visible when using LB.
However, when when something like Views field row style wanted to render a single field in isolation, a temporary EntityViewDisplay is created but not saved, and the requisite formatter settings are set on it for that single field.
Crucially, the fake/temporary display is created without a specified view mode, leaving it with the default of
\Drupal\Core\Entity\EntityDisplayBase::CUSTOM_MODE
, which is documented as being for this runtime case.Without the existing check, any runtime/fake/temporary display will have a field block added to the display.
The new flow is
Hence the check for
$this->getMode() === static::CUSTOM_MODE
.However, with the change made in the opt-in patch, we now additionally prevent this BC layer from running when LB is disabled for that view mode.
Since it will never be enabled for CUSTOM (it defaults to disabled), we no longer need this extra check.
Comment #13
alexpottThanks for updating the issue summary. Makes sense and looking at \Drupal\Core\Entity\EntityViewBuilder::getSingleFieldDisplay I can see how these are never going to have layout builder enabled via third party settings as the view mode is created there and then.
Backporting to 8.6.x since layout builder is experimental.
Committed and pushed a878a80d6c to 8.7.x and ee4efcfb77 to 8.6.x. Thanks!