Adds contextual links associated with a view display to a renderable array.
This function should be called when a view is being rendered in a particular location and you want to attach the appropriate contextual links (e.g., links for editing the view) to it.
The function operates by checking the view's display plugin to see if it has defined any contextual links that are intended to be displayed in the requested location; if so, it attaches them. The contextual links intended for a particular location are defined by the 'contextual links' and 'contextual_links_locations' properties in the plugin annotation; as a result, these hook implementations have full control over where and how contextual links are rendered for each display.
In addition to attaching the contextual links to the passed-in array (via the standard #contextual_links property), this function also attaches additional information via the #views_contextual_links_info property. This stores an array whose keys are the names of each module that provided views-related contextual links (same as the keys of the #contextual_links array itself) and whose values are themselves arrays whose keys ('location', 'view_name', and 'view_display_id') store the location, name of the view, and display ID that were passed in to this function. This allows you to access information about the contextual links and how they were generated in a variety of contexts where you might be manipulating the renderable array later on (for example, alter hooks which run later during the same page request).
$render_element: The renderable array to which contextual links will be added. This array should be suitable for passing in to drupal_render() and will normally contain a representation of the view display whose contextual links are being requested.
$location: The location in which the calling function intends to render the view and its contextual links. The core system supports three options for this parameter:
If you are rendering a view and its contextual links in another location, you can pass in a different value for this parameter. However, you will also need to set 'contextual_links_locations' in your plugin annotation to indicate which view displays support having their contextual links rendered in the location you have defined.
$view: The view whose contextual links will be added.
$display_id: The ID of the display within $view whose contextual links will be added.
template_preprocess_views_view()
function views_add_contextual_links(&$render_element, $location, ViewExecutable $view, $display_id) {
// Do not do anything if the view is configured to hide its administrative
// links.
if (empty($view->hide_admin_links)) {
// Also do not do anything if the display plugin has not defined any
// contextual links that are intended to be displayed in the requested
// location.
$plugin_id = $view->displayHandlers[$display_id]
->getPluginId();
$plugin = drupal_container()
->get('plugin.manager.views.display')
->getDefinition($plugin_id);
// If contextual_links_locations are not set, provide a sane default. (To
// avoid displaying any contextual links at all, a display plugin can still
// set 'contextual_links_locations' to, e.g., {""}.)
if (!isset($plugin['contextual_links_locations'])) {
$plugin['contextual_links_locations'] = array(
'view',
);
}
elseif ($plugin['contextual_links_locations'] == array() || $plugin['contextual_links_locations'] == array(
'',
)) {
$plugin['contextual_links_locations'] = array();
}
else {
$plugin += array(
'contextual_links_locations' => array(
'view',
),
);
}
// On exposed_forms blocks contextual links should always be visible.
$plugin['contextual_links_locations'][] = 'special_block_-exp';
$has_links = !empty($plugin['contextual links']) && !empty($plugin['contextual_links_locations']);
if ($has_links && in_array($location, $plugin['contextual_links_locations'])) {
foreach ($plugin['contextual links'] as $module => $link) {
$args = array();
$valid = TRUE;
if (!empty($link['argument properties'])) {
foreach ($link['argument properties'] as $property) {
// If the plugin is trying to create an invalid contextual link
// (for example, "path/to/{$view->storage->property}", where
// $view->storage->{property} does not exist), we cannot construct
// the link, so we skip it.
if (!property_exists($view->storage, $property)) {
$valid = FALSE;
break;
}
else {
$args[] = $view->storage->{$property};
}
}
}
// If the link was valid, attach information about it to the renderable
// array.
if ($valid) {
$render_element['#contextual_links'][$module] = array(
$link['parent path'],
$args,
);
$render_element['#views_contextual_links_info'][$module] = array(
'location' => $location,
'view' => $view,
'view_name' => $view->storage
->get('name'),
'view_display_id' => $display_id,
);
}
}
}
}
}