diff options
Diffstat (limited to 'includes/common.inc')
-rw-r--r-- | includes/common.inc | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/includes/common.inc b/includes/common.inc index 3b97014ec..863b7c099 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -5256,6 +5256,97 @@ function drupal_pre_render_link($element) { } /** + * #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: + * @code + * $node->content['links'] = array( + * '#theme' => 'links__node', + * '#pre_render' = array('drupal_pre_render_links'), + * 'comment' => array( + * '#theme' => 'links__node__comment', + * '#links' => array( + * // An array of links associated with node comments, suitable for + * // passing in to theme_links(). + * ), + * ), + * 'statistics' => array( + * '#theme' => 'links__node__statistics', + * '#links' => array( + * // An array of links associated with node statistics, suitable for + * // passing in to theme_links(). + * ), + * ), + * 'translation' => array( + * '#theme' => 'links__node__translation', + * '#links' => array( + * // An array of links associated with node translation, suitable for + * // passing in to theme_links(). + * ), + * ), + * ); + * @endcode + * + * 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: + * @code + * print render($content['links']['comment']); + * @endcode + * + * (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: + * @code + * print render($content['links']); + * @endcode + * + * 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. + */ +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; +} + +/** * #pre_render callback to append contents in #markup to #children. * * This needs to be a #pre_render callback, because eventually assigned |