Overlaps with #2334219: Make blocks expose HtmlFragmentInterface directly.
Problem/Motivation
Block are still added to the page via a render array-based hook. Per #2327277: [Meta] Page rendering meta discussion, we want to stop doing that. We want to be assembling them as first-class objects, specifically HtmlFragment objects.
Proposed resolution
hook_page_build() does more than just blocks, but we can at least move blocks off of it first. To that end, introduce code into DefaultHtmlPageRenderer that directly looks up the blocks to load, loads them, uses them as HtmlFragment objects or converts their output to HtmlFragment objects (depending on whether #2334219: Make blocks expose HtmlFragmentInterface directly goes in first or not), and then assembles them into the HtmlPage object.
In the short term much of the code from block_page_build() can be transferred directly to DefaultHtmlPageRenderer. It doesn't need to be pretty code, just no-external-interaction code. That allows us to improve it without breaking APIs. (Although if we can make it pretty, great.)
Remaining tasks
Do it, then in a follow-up issue make it pretty.
User interface changes
None.
Comments
Comment #1
wim leersIt's not quite that simple, there's an intermediary that landed some time ago: "page variants". Drupal core ships with one page variant: the
FullPageVariant. This is to enable a cleaner, simpler Panels in D8.So,
block_page_build()actually usesFullPageVariantto do the actual block building. Which means thatDefaultHtmlPageRendererwould have to callFullPageVariant, andFullPageVariantwould do the build-blocks-as-HTML-fragments stuff.But, point in case: you cannot assume blocks make up the page, the page manager makes up the page.
Comment #2
Crell commented... I must have missed that change. In that sense, actually, HtmlPageRendererInterface and FullPageVariant seem redundant?
There is a service that is fires on View, takes an HtmlFragment (or HtmlMainFragment), pulls other fragments from somewhere (eg, blocks, but not necessarily) and returns an HtmlPage. That's the high-level need. And we want it done in a way that is swappable, either per-site or per-request.
I had originally envisioned just getting the object/interface in place as a single service. If we want variability per-page, we can easily plug a chain negotiator into it like we do for several other things.
An alternative would be to make HtmlPageRenderer the negotiator, and FullPageVariant (or whatever) the service where the actual work is done. I don't have a huge preference one way or the other, I guess, as long as there's a common interface. We'd toyed with various ways to specify which page-building-thingie to use for a given route back in #2028749: Explore addressable block rendering.
Comment #3
dawehnerThose two are indeed redundant but HtmlPageRendererInterface and Variants aren't. Variants could be used for building what used to be mini panels, for example.
Comment #4
tim.plunkettI believe this is a dupe of #2295363: Blocks should be added to the page via an HtmlFragmentRenderer?