Problem/Motivation

In case someone has the idea to override NodeViewBuilder, it is basically just impossible without overring everything, as NodeViewBuilder and self
hardcodes the used classed. Both references should be replaced by static, so you can easily have a CustomNodeViewBuilder extends NodeViewBuilder.

Proposed resolution

Remaining tasks

User interface changes

API changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Wim Leers’s picture

Title: NodeViewBuilder should use static where possible » NodeViewBuilder should use static where possible, subclassing is currently too painful

Good call!

dawehner’s picture

Issue tags: +Novice
FileSize
3.27 KB

Just as a prove attached the node view builder file which was is required at the moment.

David Hernández’s picture

Status: Active » Needs review
FileSize
693 bytes

I'm not really sure if I fully understand the issue. Is only this what is required?

David Hernández’s picture

Issue tags: +Amsterdam2014

tagging.

dawehner’s picture

Status: Needs review » Needs work

@David Hernández
This is one of the problems, indeed. Other ones are more self calls and hardcoding stuff here:

      if ($display->getComponent('links')) {
        $callback = '\Drupal\node\NodeViewBuilder::renderLinks';
        $context = array(
David Hernández’s picture

Assigned: Unassigned » David Hernández

Ok, doing a deeper review on this.

David Hernández’s picture

Assigned: David Hernández » Unassigned
Status: Needs work » Needs review
FileSize
1.5 KB
1.05 KB

That's all I found. Not really experienced with PHP OOP, so not sure if it's the correct syntax to use, also I might be missing something else.

Status: Needs review » Needs work

The last submitted patch, 7: 2342683-7-nodeviewbuilder-should-be-static.patch, failed testing.

David Hernández’s picture

Assigned: Unassigned » David Hernández

Trying to fix the errors.

David Hernández’s picture

Assigned: David Hernández » Unassigned
Status: Needs work » Needs review
FileSize
1.52 KB
1.02 KB

Ok, I think that's it.

Status: Needs review » Needs work

The last submitted patch, 10: 2342683-10-nodeviewbuilder-should-be-static.patch, failed testing.

dawehner’s picture

+++ b/core/modules/node/src/NodeViewBuilder.php
@@ -35,7 +35,7 @@ public function buildComponents(array &$build, array $entities, array $displays,
-        $callback = '\Drupal\node\NodeViewBuilder::renderLinks';
+        $callback = array($this, 'renderLinks');

@@ -98,7 +98,7 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco
-    $callback = '\Drupal\node\NodeViewBuilder::renderLinks';
+    $callback = array($this, 'renderLinks');

Afaik you cannot use the actual instance but you maybe need [get_class($this), 'renderLinks']

The last submitted patch, 10: 2342683-10-nodeviewbuilder-should-be-static.patch, failed testing.

David Hernández’s picture

The function drupal_render_cache_generate_placeholder ( https://api.drupal.org/api/drupal/core%21includes%21common.inc/function/... ) checks if the $callback is a string or a "callable variable". The is_callable function ( http://php.net/manual/en/function.is-callable.php ) allows passing an object ($this) and a function name. So, that should work.

I'm not sure if afterwards, the $callback function is used in a different way, that only allows string variables. I thought also about using the get_class function, but that has a problem, as it only returns the class (NodeViewBuilder) and it should return the namespace (\Drupal\node\NodeViewBuilder).

I'm not sure why the tests are failing, I'm trying to run those tests on a clean and updated D8 installation and the tests are not passing. I've tried it in a couple other laptops and still fails.

I'm working on this.

David Hernández’s picture

Status: Needs work » Needs review
FileSize
1.53 KB

Ok, I've talked with tstoeckler and he told me that even if $callback = array($this, 'function'); should work, it usually does some weird things when working with caches.

So I replaced them with the get_class as mentioned on #13 because it seems that it returns a fully qualified domain name.

I also found that running some specific tests from the shell doesn't work and they work from the web interface. I haven't found the reason why, but I would love to know what's going on.

Status: Needs review » Needs work

The last submitted patch, 16: 2342683-16-nodeviewbuilder-should-be-static.patch, failed testing.

David Hernández’s picture

Status: Needs work » Needs review
FileSize
1.53 KB

Ok, next try. We can't use get_class($this) on the renderLink function because it's a static function and $this will not be defined. We can't use get_class because it returns the parent class (NodeViewBuilder). I'm using get_called_class() as it should return the child class, but locally some tests are failing.

Is there any function like getClass() to be able to do some late static binding? http://php.net/manual/en/language.oop5.late-static-bindings.php

dawehner’s picture

+++ b/core/modules/node/src/NodeViewBuilder.php
@@ -35,7 +35,7 @@ public function buildComponents(array &$build, array $entities, array $displays,
-        $callback = '\Drupal\node\NodeViewBuilder::renderLinks';
+        $callback = get_class($this) . '::renderLinks';

@@ -98,7 +98,7 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco
-    $callback = '\Drupal\node\NodeViewBuilder::renderLinks';
+    $callback = get_called_class() . '::renderLinks';

Well, in that case we should try to use the same method if possible, but cool that you figured that out.

Berdir’s picture

Status: Needs review » Needs work

Setting to needs work for using the same approach for both cases.

Wim Leers’s picture

Issue tags: +php-novice

Thanks for working on this! :)

David Hernández’s picture

Status: Needs work » Needs review
FileSize
1.53 KB

New patch. Is there any other class where this is happening?

During DrupalCon I found the CommentViewBuilder ( https://www.drupal.org/node/2348547 ) and we created the issue.

Wim Leers’s picture

Status: Needs review » Needs work

Setting to needs work for using the same approach for both cases.

Berdir’s picture

@WimLeers: Looks like the new patch is doing that now? static:: is fine.

dawehner’s picture

Status: Needs work » Reviewed & tested by the community

During DrupalCon I found the CommentViewBuilder ( https://www.drupal.org/node/2348547 ) and we created the issue.

Nice!

@Wim Leers
It would be great if this pattern is part of some documentation of how to use the render cache patterns.

Wim Leers’s picture

It would be great if this pattern is part of some documentation of how to use the render cache patterns.

Sure, but where would we document something like this? It's not something strongly related to render caching, it's really a general "static method invocations when writing a class that may be subclassed" kind of problem, which is something that applies to Drupal 8 in general, since we now are so heavily OOPified.
In any case: I'm open to suggestions :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 1688321 and pushed to 8.0.x. Thanks!

  • alexpott committed 1688321 on 8.0.x
    Issue #2342683 by David Hernández, dawehner: Fixed NodeViewBuilder...

Status: Fixed » Closed (fixed)

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