Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Currently towards the end of ds_entity_variables(), there is a call to hook_ds_pre_render_alter().
However:
- It seems that from this hook you do not reliably know which layout you are dealing with.
- Implementing this hook for just one layout adds unnecessary overhead for other node rendering where this layout is not used.
(ok it won't be devastating, but just slightly more than necessary.)
Solution: Allow layouts to specify one (or more) pre_render callbacks, like so:
function hook_ds_layout_info() {
$layouts = array(
'foo_1col' => array(
[..]
'pre_render' => array('_mymodule_mylayout_pre_render'),
),
);
return $layouts;
}
And then call them from ds_entity_variables(), like so:
// Let other modules alter the ds array before creating the region variables.
$context = array('entity' => isset($vars[$object]) ? $vars[$object] : (isset($vars['elements']['#' . $object]) ? $vars['elements']['#' . $object] : ''), 'entity_type' => $vars['elements']['#entity_type'], 'bundle' => $vars['elements']['#bundle'], 'view_mode' => $vars['elements']['#view_mode']);
drupal_alter('ds_pre_render', $layout_render_array, $context, $vars);
// Let the layout itself alter the ds render array.
if (!empty($layout['pre_render']) && is_array($layout['pre_render'])) {
foreach ($layout['pre_render'] as $callback) {
if (function_exists($callback)) {
$callback($layout_render_array, $context, $vars);
}
}
}
foreach ($layout_render_array as $region_name => $content) {
Also:
- Make the $layout variable available to the regular hook_ds_pre_render_alter()
- In addition to a pre_render(), allow layouts to specify a preprocess callback, that behaves like a regular hook_preprocess_node(), but is called from ds_entity_variables().
Comments
Comment #1
donquixote CreditAttribution: donquixote as a volunteer commentedComment #2
donquixote CreditAttribution: donquixote as a volunteer commentedOh, another idea:
What if you add the $layout variable in hook_entity_view_alter() ?
and then in ds_entity_variables() we no longer need to call ds_get_layout().
This makes the layout available to other modules earlier, and it even allows them to alter it. They could even "invent" layouts ad-hoc, that don't even exist in the database!
Comment #3
aspilicious CreditAttribution: aspilicious commentedHmmm, I don't think I'm going to change this for D7.
D8 already uses hook_entity_view_alter. So we don't need that.
But I'm intrigues about the pre render stuff.
We use the layout plugin module now in D8 so I'm not sure if that plays nicely with your ideas.
Comment #4
aspilicious CreditAttribution: aspilicious commentedMoving to layout plugin queue as layouts are registered there now.
Comment #5
dsnopekWould using a preprocess function be enough?
I'm not really familiar with the DS codebase in Drupal 7, so I don't really know where
ds_entity_variables()
fits into the pipeline, and maybe you need to alter something before preprocess runs?But if a preprocess function would work, you can declare one for any specific layout! For example, if the layout is
ds_1col
, you can implement:Some changes might be necessary to
ds_theme_registry_alter()
to make sure that user-provided preprocess functions run AFTER the ones from Display Suite, but we shouldn't need to change anything in Layout Plugin to make this work!Comment #6
donquixote CreditAttribution: donquixote as a volunteer commentedI don't remember the exact use case, but there are some things you can do in pre_render that you cannot do in a preprocess.
- Change the theme hook.
- Attach a wrapper, prefix, or suffix.
- Totally remodel the render array.
I think when I created the issue, I had my reasons not to just ask for a preprocess - just don't remember now.
Comment #7
Anonymous (not verified) CreditAttribution: Anonymous commentedHey,
I just wanted to do some styling in my site where I have layouts and it occurred to me that I cannot target specific layouts since there is no attributes that I can use. So I wanted to propose adding (content_/wrapper_)attributes variable via preprocess function. Seems this is the right place to suggest that. I see no reason why layouts shouldn't have a common preprocess handler.
Comment #8
dsnopek@ivanjaros: I'm not sure I understand. Can you elaborate on what you're trying to accomplish?
Adding a preprocess function to all layouts should be easy to do, here's an example:
... however, I'm not sure that's really very useful, since the template for each layout doesn't necessarily contain the same stuff. And actually, it's possible to make a layout that doesn't use a template at all (like a flexible layout builder where you construct the layout in the UI), although I expect that will be a very rare case.
Comment #9
Anonymous (not verified) CreditAttribution: Anonymous commenteddsnopek: basically just:
I ended up hardcoding attributes in all templates. But having preperocess handler that would provide attributes with some basic data, like layout name, would be more preferable.
Comment #10
DamienMcKennaNo further work has been made to this module since 8.3.0 was released, almost a year ago, all efforts should be made to switch over to core's Layout Discovery system instead.