Posted by seanberto on April 26, 2011 at 6:41pm
Geek question for the PDX clan,
Anyone got any ideas for why there's not render array for links in D7? There's theme_links() in theme.inc. But why does the theme engine in D7 not take advantage of render arrays? Menu module does not define a render array for menu links either, which maybe isn't it's job, but would seem to make theming overrides much easier than hacking out your own MYTHEME_links() function in template.php.
Any thoughts? (Mikey_p, I know you got something...)
-s

Comments
Sounds like yet another entry
Sounds like yet another entry for d7wtf.com.*
That's probably to harsh.. D7
That's probably to harsh.. D7 isn't any different than any other previous version of Drupal in this regard (i.e. why were menu links not preprocessed like everything else in D6?) but I think the changes stand out more in D7 because of the number of radical changes that have been made (render API, entities, etc) make the areas that didn't get updated seem more out of date.
I have to keep reminding myself that this is only Drupal 7.0 still, and we haven't even made it to a point release yet (although it's probably coming soon) so it's fair to give D7 some slack, since I know we're doing way more with 7.0 than almost anyone did with 6.0.
Huh...
I don't think you were being harsh, just kidding around. ;)
Would there be value in me trying to write a patch to menu module to get some renderable arrays in place? I'm guessing that it won't likely get accepted, but what the heck, if it doesn't break anything. It's all display side afterall.
If I were to create a renderable array for Menu module, what "types" should be defined? I can think of two off-hand - one that generates basically the same output as menu_tree_output(), and another that replicates menu_navigation_links().
Obviously these aren't critical isssues to solve for D7. I'm mainly interested as an exercise in understanding hook_element_info() and the guts of renderable arrays.
I don't see why this couldn't
I don't see why this couldn't be done in a contrib module. It'd give you a good change to get the code stable before submitting a patch for D8.
I doubt it'd get into D7 as too much of an API change.
Elaborate please
What specifically are you trying to do? Looks to me like menu_tree_output() arranges menu links in a render array, and node_build_content() uses a render array for node links.
Where a render array isn't used, you still have room for tweaking via hook_preprocess_links(), which can adjust $variables. Within such a preprocess function, you can also set $variables['theme_hook_suggestions'][] to something like 'links__MY_SPECIAL_TYPE', so that your theme can customize markup for just that set of links via MYTHEME_links__MY_SPECIAL_TYPE().
Just looking for consistency, and perhaps cleaner overrides
@Effulgentsia, I'd not seen menu_tree_output(). Thx. I'd just being doing something like $variables['$MYMENU'] = theme('links', menu_tree($menu_name)), or theme('links', menu_navigation_links($menu_name)) - depending upon the markup that I was looking for...
Regarding render arrays, I guess that I'm just looking for consistency in approach. Something like render(&$main_menu) provides a lot of flexibility with all the additional properties/functions that it provides. Also, you could do cool stuff like add a hook_element_info_alter() call in a module.
Another great little feature that could be added to something like menu_element_info() would be a "separator" property that defaults to NULL. Then, in 6 lines of module code you could add a custom separator. Something like:
MYMODULE_element_alter(&$element) {switch ($element) {
case 'menu':
$element['#separator'] = '|';
break;
}
return $element;
}
hook_element_alter() would be cool
One of the current limitations of drupal_render() is that all you have is hook_element_info_alter(), which means you can only alter the definition of an element type, and therefore only add #pre_render callbacks (or whatever other callbacks) for elements that have a #type. And you'll find a bunch of render arrays throughout D7 don't have a #type, only a #theme, as in the case of what menu_tree_output() returns. This pretty much sucks, and IMO, is worth fixing in D8. If you want to start submitting patches to D8 that set a #type on more render arrays, that would be awesome. I doubt those patches would qualify for backporting to D7, but who knows.
I don't know if your above example code intended to imply this, but another approach would be to add a hook_element_alter() for drupal_render() to invoke on the element itself, as a complement to hook_element_info_alter(), which acts on type definitions only. I think this would be pretty sweet, but I think it might add too much performance slow down to be accepted.
In general, what we're able to do on render arrays, is still pretty primitive, compared to, say, what jQuery can do on a DOM. http://developmentseed.org/blog/2009/mar/01/limitations-drupal-theme-layer contains some great ideas for improvement, and I'd love to see some of them implemented in D8, but again, we're constrained by PHP's function call overhead. Maybe something clever can be figured out though, it'll just take a lot of experimentation, which means people with enough time on their hands to delve into attempting some different approaches.
Keep in mind though, that a lot can be achieved via the theme system and preprocess functions. If you find yourself stuck at the render layer, you can maybe get unstuck at the theme system layer. One of the things that's happened in D7 is that there's now often many ways to achieve the same goal. There's a bazillion alter hooks. There's #pre_render. And there's theme preprocess functions. I think we'll all be learning a lot in the next year on when to use what, and hopefully applying that knowledge towards simplifying it all for D8. And like mikey_p says above, there's a lot of improvements you can try via writing a D7 contrib module. Attempting that is a great way to learn, and putting it out there is a great way to collect feedback from a variety of use-cases. It also means people get to benefit from it now, and not wait for a D8 release, and it helps the chances of the improvement making it into D8 core, since it's been "battle tested".
Great ideas
Some of the great ideas have come to life in dvessel's RendElements http://drupal.org/sandbox/dvessel/1122312 Like using attribute selector on Drupal's array properties. e.g.
*:emptyto get the empty regions,content nodes > *:first-childto get the first node of a river or news. Cool stuff!goodby theme()
Whatch the presentation The Render API in Drupal 7 (http://chicago2011.drupal.org/sessions/render-api-drupal-7) and hear Franz Heinzmann explain that there are (still) two ways to get render output 1. the old
theme('...')method and 2. the new Drupal 7 render arrays. The first could not be removed from Drupal 7 due to the large code impact and the limited time remaining. Your theme_links is part of the D6 legacy. Feel free to provide new code for D8.