function drupal_pre_render_links

Same name in other branches
  1. 8.9.x core/includes/common.inc \drupal_pre_render_links()

#pre_render callback that collects child links into a single array.

This function can be added as a pre_render callback for a renderable array, usually one which will be themed by theme_links(). It iterates through all unrendered children of the element, collects any #links properties it finds, merges them into the parent element's #links array, and prevents those children from being rendered separately.

The purpose of this is to allow links to be logically grouped into related categories, so that each child group can be rendered as its own list of links if drupal_render() is called on it, but calling drupal_render() on the parent element will still produce a single list containing all the remaining links, regardless of what group they were in.

A typical example comes from node links, which are stored in a renderable array similar to this:

$node->content['links'] = array(
    '#theme' => 'links__node',
    '#pre_render' => array(
        'drupal_pre_render_links',
    ),
    'comment' => array(
        '#theme' => 'links__node__comment',
        '#links' => array(),
    ),
    'statistics' => array(
        '#theme' => 'links__node__statistics',
        '#links' => array(),
    ),
    'translation' => array(
        '#theme' => 'links__node__translation',
        '#links' => array(),
    ),
);

In this example, the links are grouped by functionality, which can be helpful to themers who want to display certain kinds of links independently. For example, adding this code to node.tpl.php will result in the comment links being rendered as a single list:

print render($content['links']['comment']);

(where $node->content has been transformed into $content before handing control to the node.tpl.php template).

The pre_render function defined here allows the above flexibility, but also allows the following code to be used to render all remaining links into a single list, regardless of their group:

print render($content['links']);

In the above example, this will result in the statistics and translation links being rendered together in a single list (but not the comment links, which were rendered previously on their own).

Because of the way this function works, the individual properties of each group (for example, a group-specific #theme property such as 'links__node__comment' in the example above, or any other property such as #attributes or #pre_render that is attached to it) are only used when that group is rendered on its own. When the group is rendered together with other children, these child-specific properties are ignored, and only the overall properties of the parent are used.

3 string references to 'drupal_pre_render_links'
comment_build_content in modules/comment/comment.module
Builds a structured array representing the comment's content.
node_build_content in modules/node/node.module
Builds a structured array representing the node's content.
ThemeLinksTest::testDrupalPreRenderLinks in modules/simpletest/tests/theme.test
Test the use of drupal_pre_render_links() on a nested array of links.

File

includes/common.inc, line 5971

Code

function drupal_pre_render_links($element) {
    $element += array(
        '#links' => array(),
    );
    foreach (element_children($element) as $key) {
        $child =& $element[$key];
        // If the child has links which have not been printed yet and the user has
        // access to it, merge its links in to the parent.
        if (isset($child['#links']) && empty($child['#printed']) && (!isset($child['#access']) || $child['#access'])) {
            $element['#links'] += $child['#links'];
            // Mark the child as having been printed already (so that its links
            // cannot be mistakenly rendered twice).
            $child['#printed'] = TRUE;
        }
    }
    return $element;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.