API page: https://api.drupal.org/api/drupal/core%21modules%21views%21src%21Plugin%...
I would suggest to make StylePluginBase::renderFields(array $hresult) public instead of protected.
The module Views Merge Rows is a display extender plugin that modify Views output by implementing hook_views_pre_render(). As the module needs to access $view->style_plugin->rendered_fields during pre-rendering process, and because $view->style_plugin->rendered_fields is not rendered prior to the execution ofhook_views_pre_render, invoking $view->style_plugin->renderFields($view->result) is made necessary.
The access in the code is as follows:
$view->style_plugin->renderFields($view->result);
$rendered_fields = $view->style_plugin->getRenderedFields();
Prior to the proposed solution, creating a derived class of StylePluginBase was considered. However, the required property would not spread throughout all style plugins. The latter is pre-requisite because Views Merge Rows is a display extender intended to work with any style plugin.
Issue fork drupal-2824920
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
cilefen commentedComment #3
dgagne commentedComment #5
dgagne commentedComment #6
dawehnerIs there a reason you cannot use
\Drupal\views\Plugin\views\style\StylePluginBase::getField?Comment #7
dgagne commentedThe reason is that I need to access cached fields (in $rendered_fields) and before accessing them, I have to cache the fields because this is not done automatically before hook_pre_render is called. You may refer to https://www.drupal.org/node/2826755 to get more info.
Comment #8
dgagne commentedComment #10
dgagne commentedComment #11
josevitalsoutoPatch
Comment #13
pixelcab commentedI'll work on this as part of Drupal Global Sprint Weekend
Comment #14
pixelcab commentedI was able to successfully apply the patch to my local Drupal 8.4.0-dev instance. The renderFields method of the StylePluginBase class was successfully changed from protected to public. I was able to verify the patch is working by testing the change using the development version (8.x-1.0-dev) of the views_merge_rows.module which was already using the public version of the renderFields method. After applying the patch the module had the correct access to use the renderFields method.
Comment #15
dawehnerIMHO we need a clear issue summary why making this public is the only right way to solve it. Is there not maybe an underlying problem? Is there maybe a better way to solve this particular problem? Should there we a
FieldAwareStylePluginInterfacewhich exposes some of that kind of information?Just making something public without a clear vision is IMHO not the right fix for a problem.
Comment #16
dawehnerI'm also curious whether we need this issue as well as #2829046: Create public $DisplayPluginBase::getExtender($id)
Comment #17
dgagne commentedComment #18
dgagne commentedComment #19
dgagne commentedComment #20
dgagne commented@dawehner:
I think implementing a
FieldAwareStylePluginInterfacewould be similar to use a nuke to kill a fly. The method is defined directly inStylePluginBaseand any style plugin extending it can access it. I don't see any reason why we should put this method in an interface. If it was defined inPluginBase(which is extended byStylePluginBase), my answer would have been different.Comment #21
dgagne commentedComment #22
xjmSetting NR for @dawehner to review @dgagne's updated proposal in the summary. Thanks for your contributions on Views!
Comment #23
dgagne commentedComment #24
andypostthere's no render at pre render stage! indeed)
And the main question in why not inherit your style plugin from base one and alter discovery or views style plugins with own implementation?
Yep, that may cause incompatibilities like #2853002: Collision with ctools_views
Comment #25
xjmHi @dgagne,
I recommend discussing what you want to accomplish at a somewhat higher level in a single issue, so as not to fragment the discussion. Here are the related issues:
It should probably be possible to accomplish what you want to try without adding to the API surface like this. So I'd look more into @andypost's suggested directions in #24, and maybe explain the usecase in a bit more detail.
Thanks!
Comment #26
dgagne commentedHi,
Before going forward, I just realized the proposed method
$DisplayPluginBase::getExtender(id)is not needed. I was able to use another option.Now, here is a quick wrap-up. I ported Views Merge Rows to Drupal 8 few months ago because the module maintainer doesn't work on the project anymore. Basically, VMR is run through
hook_views_pre_render()and a display extender plugin is designed to define a merge option on a per-field basis. Currently, no style plugin is coded in the module.Here is a sample of the relevant Drupal 7 code (
hook_views_pre_render()):My main concern was to keep the module behavior as is. So, here is a sample of the relevant Drupal 8 code (
hook_views_pre_render()) as it is currently, assuming patches as they are currently proposed are applied:Now, regarding @andypost suggestions:
"And the main question in why not inherit your style plugin from base one and alter discovery or views style plugins with own implementation?"
Duplicating current views style plugins would work (I tested the option), but as I pointed out in a prior comment, the module users would be constrained to remain within these and this is not the module's intent. It is intended to be used with whatever Views style the user decides to use. This also has the drawback to duplicate styles in the selection form.
Inheriting a style plugin from base was also looked at before proposing the patches. But as mentioned before, required properties/methods would not be available to default styles. I could alter discovery here (would need to know how to implement that), but once again it would go against the intents behind the module.
With regards to making
renderFields()method public, I don't think there is an issue here. The only way I could get rid of that need would be to use another hook where$rendered_fieldshas been rendered, but I still need an access to that data to manipulate it.I am really open to suggestions. I would really be happy to close the issues before version 8.4 is released. I am not comfortable to tell my users to patch the core to use the module with Drupal 8. Many thanks in advance.
Comment #27
dgagne commentedComment #28
dgagne commentedI forgot, here is a sample of
renderFields():The function is called at rendering. It is explicitely checking whether
$rendered_fieldsalready exists. I examined the code and my understanding is that such case can only happen ifrenderFields()is run prior to rendering the view. So I also understand there is an implicit assumption here thatrenderFields()can be run during the pre-rendering process.So, there is evidence that this method was intended to be public.
Comment #30
colan@dgagne: Would you (or someone else that understands the problem) be able to update the issue title and summary with #26 and #28? It would make it much easier for core maintainers to review your original intent, rather than seeing this issue simply as a way to make something public.
Core reviewers/maintainers: Would you kindly take another look at this in the meantime given #26 and #28? This is currently causing #2868486: Call to protected method StylePluginBase::renderFields() in views_merge_rows_views_pre_render() and preventing Views Merge Rows from being usable without hacking core. Thanks!
Comment #38
mlncn commentedThe patch still applies, still works, and is still needed. This 'non-public' API has stayed stable for five years across two major versions of Drupal.
But bottom line, a module needs it and no one has raised a specific objection. Drupal should not be trying to protect developers from themselves but making the tools available to build what it can. Please, let's not keep unnecessary barriers to extending Drupal!
Comment #39
ecj commentedWorks like a charm! awaiting to become official patch for views.
Comment #40
alexpottThis method could be private for all of core usages... also I feel that it needs to be looked at alongside #2826755: Create a public read/write interface for $StylePluginBase::rendered_fields as views merge rows requires both patches to work. The work in 2826755 makes me feel uneasy because the idea of swapping out rendered things with setRenderedField() looks like a side-effect bug waiting to happen.
Comment #41
lendudeJust looking at the code of StylePluginBase::renderFields, it reads very much as internal code. Passing something that doesn't match the very vague description of "The result array from $view->result" will probably blow up your View, and there is zero validation of the input in this method (there doesn't need to be, it's protected after all).
At the very least, I think, making this public would require that we give this dedicated test coverage that shows that this is robust enough to be public API. Also we would need to have better documentation on the method to specify what we expect this method to do, and what we expect the result of calling this to be and why you might need to call it from outside the context of the current View rendering pipeline.
Comment #46
brainiacque commentedIs this patch still required for Drupal 10? Composer will not apply this patch; however, I still get errors when building views with this module.
EDIT: Never mind. I was using 'drupal/view_merge_rows' as the project.
Comment #47
rajivgandhi chinnakrishnan commentedAfter applying the patch from (#11), we are getting the below error in 10.3.1. The below patch is the solution for the same.
Comment #48
mlncn commentedComment #49
wolcen commentedUpdate of the protected->public patch piece only.
Comment #51
ruslan piskarovFor Drupal 11.3.3+.