Problem/Motivation

As started on #1811828: Use #attached to find the css/js of a view the goal is to proper support element level caching for a view.

In order to achieve this it was experimented to convert a normal view to a render element, but due to different problems like block titles / page titles this got deferred.

Most of the problems are caused by the fact that we HAVE (!!!!!) to support to not only return render arrays but also for example proper response objects (or, currently, plain strings). This is necessary because Views supports not only rendering to HTML, but also to RSS and other formats (think REST/serializer), while render arrays only support HTML!

Proposed resolution

  • Move most of the views rendering into a view element and its #pre_render functionality
  • In order to use a pre_render approach we have to move the contextual links adding into pre_render as well
  • Allow to specify whether a display returns a render array (like blocks) or should return a response object (like feed).
    In case you return a response object call executeDisplay, otherwise call buildRenderable
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

Issue summary: View changes
Status: Active » Needs review
FileSize
5.24 KB

I know that I implemented exactly that once before, maybe in another issue or just as an experiment, though no idea where, so here is one.

Status: Needs review » Needs work

The last submitted patch, 1: render_element-1849822-1.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
7.48 KB

Not really have the motivation to work on it but here is at least one less bug to fix.

Most of the problems is caused by the fact that we HAVE (!!!!!) to support to not only return render arrays
but also for example proper response objects, given that for example a rss output is not handled via the render component
but via the rest/serializer code path.

Status: Needs review » Needs work

The last submitted patch, 3: 1849822.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
11.91 KB
5.69 KB

Let's see.

Status: Needs review » Needs work

The last submitted patch, 5: 1849822-5.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
14.15 KB
3.05 KB

I just hate phpunit failures!

Status: Needs review » Needs work

The last submitted patch, 7: 1849822-7.patch, failed testing.

Wim Leers’s picture

Title: Convert the view rendering to a render array » Convert (HTML) view rendering to a render array
Issue summary: View changes
Issue tags: +Performance, +D8 cacheability

Updated issue summary, particularly to include the info in #3.

Wim Leers’s picture

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.29 KB
3.56 KB

Thank you for the great pointer. I guess this patch could be green with this already.

Status: Needs review » Needs work

The last submitted patch, 11: view_render-1849822-11.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.59 KB

Ha, I am glad that we do have such a good test coverage.

Wim Leers’s picture

Status: Needs review » Needs work

AWESOME! :)

  1. +++ b/core/modules/views/src/Annotation/ViewsDisplay.php
    @@ -131,4 +131,11 @@ class ViewsDisplay extends ViewsPluginAnnotationBase {
    +   * Whether the plugin returns a response object.
    +   *
    +   * @var bool
    +   */
    +  public $return_response;
    

    Shouldn't this then be called returns_response?

    And s/the plugin/the views display plugin/?

  2. +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
    @@ -2221,6 +2219,25 @@ public function preExecute() {
    +   * Builds a render array when the view is rendered as render array.
    

    This reads a bit bizarre :P

  3. +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
    @@ -2221,6 +2219,25 @@ public function preExecute() {
    +    $build = [
    +      '#type' => 'view',
    +      '#name' => $this->view->storage->id(),
    +      '#display_id' => $this->display['id'],
    +      '#arguments' => $args,
    +      '#embed' => FALSE,
    +      '#view_executable' => $this->view,
    +    ];
    +
    +    return $build;
    

    Why assign to a variable first if you're just going to return it anyway?

  4. +++ b/core/modules/views/src/ViewExecutable.php
    @@ -1396,6 +1396,31 @@ public function render($display_id = NULL) {
    +   * This render array has a #pre_render callback which will call
    +   * ::executeDisplay in order to actually execute the view etc.
    

    Seems like this comment could use some polish.

  5. +++ b/core/modules/views/src/ViewExecutable.php
    @@ -1396,6 +1396,31 @@ public function render($display_id = NULL) {
    +  public function buildRenderForDisplay($display_id = NULL, $args = array()) {
    

    We usually call the building of a render array build(). This is true for block rendering, entity rendering, etc. Hence buildDisplay() would be a more consistent name, if that would still make sense within Views land?

  6. +++ b/core/modules/views/src/ViewExecutable.php
    @@ -1396,6 +1396,31 @@ public function render($display_id = NULL) {
    +    // @todo Extract that into a generic method.
    

    Should this still happen in this patch, or…?

  7. +++ b/core/modules/views/src/ViewExecutable.php
    @@ -1396,6 +1396,31 @@ public function render($display_id = NULL) {
    +    return $this->display_handler->buildRender($args);
    

    … and this would then be called build().

  8. +++ b/core/modules/views/views.module
    @@ -97,9 +99,27 @@ function views_views_pre_render($view) {
    +      // Add contextual links to the view. We need to attach them to the dummy
    +      // $view_array variable, since contextual_preprocess() requires that they be
    +      // attached to an array (not an object) in order to process them. For our
    +      // purposes, it doesn't matter what we attach them to, since once they are
    +      // processed by contextual_preprocess() they will appear in the $title_suffix
    +      // variable (which we will then render in views-view.html.twig).
    

    80 cols.

  9. +++ b/core/modules/views/views.module
    @@ -97,9 +99,27 @@ function views_views_pre_render($view) {
    +      views_add_contextual_links($element, 'view', $view, $view->current_display);
    

    WOOT! This changes it so that contextual links are added in the #pre_render stage rather than in the theme preprocess stage, which is much cleaner!

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.65 KB
10.51 KB

Thank you for the fast review!

Shouldn't this then be called returns_response?

And s/the plugin/the views display plugin/?

True

This reads a bit bizarre :P

Just like render arrays itself ;)

Why assign to a variable first if you're just going to return it anyway?

Maybe you know an answer. One reason are debugging purposes

Seems like this comment could use some polish.

This comment could be more specific.

We usually call the building of a render array build(). This is true for block rendering, entity rendering, etc. Hence buildDisplay() would be a more consistent name, if that would still make sense within Views land?

Decided to go directly with buildRender to be more in sync with the method on the display.

Should this still happen in this patch, or…?

Nope, this is a general todo. You will find similar code snippets in various places in views.
Can we PLEASE stop the business of make it hard for people to think out loud in code? A todo itself is a fine thing and having one
is 100times MUCH better than be silent about it. Having a follow up just adds a bit on top of it.

80 cols.

fixed.

Wim Leers’s picture

Status: Needs review » Needs work

Can we PLEASE stop the business of make it hard for people to think out loud in code? A todo itself is a fine thing and having one
is 100times MUCH better than be silent about it. Having a follow up just adds a bit on top of it.

I know! I agree!
But at the same time, you can't blame reviewers for not knowing what the scope of a @todo is: it can be either meant as a reminder for something that should happen in a next reroll of the patch, or it could be meant to be committed.

Decided to go directly with buildRender to be more in sync with the method on the display.

Why not just build()? buildRender() is confusing because it's two consecutive verbs. If you want to stick with what you have, buildRenderable() would be easier to understand.

Plus one final nitpick:

+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -2221,6 +2219,26 @@ public function preExecute() {
+   * Note: This does not contain yet the executed view, but just the loaded

s/does not contain yet/does not yet contain/

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.65 KB
693 bytes

Why not just build()? buildRender() is confusing because it's two consecutive verbs. If you want to stick with what you have, buildRenderable() would be easier to understand.

Sure, there is overriding by arguments in programming languages like C++, but I haven't seen an example of overriding by intention. ViewExecutable::build() already exists out there.

But at the same time, you can't blame reviewers for not knowing what the scope of a @todo is: it can be either meant as a reminder for something that should happen in a next reroll of the patch, or it could be meant to be committed.

Good point.

Fixed the nitpick.

Wim Leers’s picture

ViewExecutable::build() already exists out there.

Good point. Missed that, sorry.

I still think ::buildRenderable() would be better though. I think you might've missed that?

dawehner’s picture

FileSize
16.7 KB
6.42 KB

Yeah I pretty much ignored that bit totally

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community

Hehe :)

No more complaints!

dawehner’s picture

Cool, thank you.

effulgentsia’s picture

Priority: Normal » Major

If needed for performance (caching), should be Major priority.

Dries’s picture

Status: Reviewed & tested by the community » Needs work

This patch needs a quick re-roll because some test files where moved around. Otherwise this looks good to me.

moshe weitzman’s picture

For the record, the most recent patch did not apply cleanly but it would have applied cleanly as a git merge (or rebase). I posted the details to www.mosheweitzman.me/post/96720635168/improve-drupal-org-code-workflow-w...

dawehner’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
16.74 KB

Merge, rebase whatever.

alexpott’s picture

It'd be great if the summary can be updated with the actual resolution.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Meant to set to needs work to get the issue summary updated.

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.78 KB

Rerolled.

Wim Leers’s picture

Status: Needs review » Needs work

Great that this was set to NR so testbot picks this up, but back to NW per #26/#27.

dawehner’s picture

Issue summary: View changes
Status: Needs work » Needs review

Meh.

Status: Needs review » Needs work

The last submitted patch, 28: views-1849822-28.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
16.99 KB
1.29 KB

I am so glad that we have at least some basic level of test coverage.

Status: Needs review » Needs work

The last submitted patch, 32: views-1849822-32.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
20.77 KB
4.47 KB

Let's fix them.

dawehner’s picture

FileSize
18.12 KB

No, I don't want to get rid of tests.

The last submitted patch, 34: views-1849822-34.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 35: views-1849822-35.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
18.14 KB
713 bytes

Or that?

Status: Needs review » Needs work

The last submitted patch, 38: views-1849822-38.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
18.15 KB
735 bytes

or that?

Status: Needs review » Needs work

The last submitted patch, 40: views-1849822-40.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
627 bytes
18.13 KB

meh.

Status: Needs review » Needs work

The last submitted patch, 42: views-1849822-42.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
18.83 KB
710 bytes

The remaining two failures are maybe impossible to understand.

Status: Needs review » Needs work

The last submitted patch, 44: views-1849822-44.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
18.3 KB
18.32 KB
3.7 KB

There we go, how annoying is that ... Fixed it.

The last submitted patch, 46: 1849822-46.patch, failed testing.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed 7652f68 on 8.0.x
    Issue #1849822 by dawehner: Convert (HTML) view rendering to a render...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.