Follow-up to / Helper for #2407195: Move attachment processing to services and per-type response subclasses
Problem/Motivation
renderRoot() returns a 'string', but that is wrong, because this is the root of the tree and hence we must take cacheable meta data into account.
Proposed resolution
Before:
$this->renderer->renderRoot($html);
$content = $this->renderCache->getCacheableRenderArray($html);
After:
$content = $this->renderer->renderRootReplacementNeedsAName($html);
If someone still needs to use the markup directly, they can do:
print $content['#markup']
on their own risk.
Remaining tasks
- Decide the new method name (it should not actually be
renderRootReplacementNeedsAName()
) and add it. Add documentation torenderRoot()
about the new method as well as about the workaround above that is required for it to be cacheable. - Convert those core uses that should be
renderPlain()
already torenderPlain()
(i.e. simple renderables with no assets or caching requirements). - Convert remaining core usages to the new method.
- Deprecate
renderRoot()
.
User interface changes
- None
API changes
- New method returns a cacheable render array.
BETA EVAL:
It is a major bug, because if you get back a string, you expect to use that => cacheability metadata lost => security issues.
Comments
Comment #1
Fabianx CreditAttribution: Fabianx for Acquia commentedPostponing on #2407195: Move attachment processing to services and per-type response subclasses, there is more work involved than I thought ...
Comment #2
Fabianx CreditAttribution: Fabianx for Acquia commentedComment #3
dawehnerComment #4
Wim LeersIs this really major? I think you marked it as major based on your discussions with Crell, where you concluded that if every bit of rendering that
Renderer
does returns such a thin render array, that we enable significant clean-up/simplification elsewhere?If so, could you please explain that in the IS? Currently, this issue looks like it's a minor nice-to-have.
Comment #5
Fabianx CreditAttribution: Fabianx for Acquia commentedYes, it is major, because if you get back a string, you expect to use that => cacheability metadata lost => security issues.
Comment #6
Wim LeersAha :) Could you update the IS with that? Thanks!
Comment #7
Fabianx CreditAttribution: Fabianx for Acquia commentedComment #8
serg2 CreditAttribution: serg2 commentedThis was postponed on #2407195: Move attachment processing to services and per-type response subclasses which is now fixed so marking as needs work. (hope that is correct & okay!)
Comment #9
star-szrIs this still possible to do now? It feels like too big of an API change but maybe I'm misunderstanding something…
Comment #10
dawehnerI have to agree with @Cottser. Even you are supposed to not call renderRoot() directly, we still have 80 calls to it, so the chance is not unlikely that people use it.
Comment #12
xjmSo the "correct" replacement for most
renderRoot()
usages is probablyrenderPlain()
, correct? Would it be correct to markrenderRoot()
internal? The docs say:So the first case is clearly internal, but the second makes it sound like public API. And the second case is not a scenario where cacheability metadata matters anyway, is it? Or is it?
This change definitely could not happen in a patch release, but I can see the case for treating it as a security hardening and allowing the small BC break in a minor, with CR etc.
Comment #13
joelpittetWith value objects this would kinda make sense/work. But It seems very strange to me that a 'render' function would produce yet another array. Also a huge API change, IMO. When working with the system it just feeds like another barrier to use this API. #death_to_arrays_as_value_objects
Comment #14
alexpottIf book export broken because of this?
Or does a something come and grab the cacheable metadata later?
Comment #15
lauriiiI suggest that we create a new method, remove all usages of the old method in core and finally deprecate it.
Comment #16
xjmWe discussed this issue with @alexpott, @Cottser, @lauriii, and @joelpittet at DrupalCon New Orleans. We discussed that the original proposal is probably too disruptive to change in a minor release, because it is a non-BC change to the return value of an API method that we can't really call internal based on its current usage. However, we agreed that it is a major issue. The path forward is:
renderRootReplacementNeedsAName()
) and add it. Add documentation torenderRoot()
about the new method as well as about the workaround above that is required for it to be cacheable.renderPlain()
already torenderPlain()
(i.e. simple renderables with no assets or caching requirements).renderRoot()
.