ccl_local_actions.module in Custom Contextual Links 8
Same filename and directory in other branches
Adds the ability to create local tasks with CCL.
File
ccl_local_actions/ccl_local_actions.moduleView source
<?php
/**
* @file
* Adds the ability to create local tasks with CCL.
*/
/**
* Implements hook_form_FORM_ID_alter().
*
* Add additional form elements to the main CCL add/edit form.
*/
function ccl_local_actions_form_ccl_add_form_alter(&$form, &$form_state, $form_id) {
// Check if we are in edit mode.
if (isset($form_state['clid'])) {
$clid = $form_state['clid'];
$link = $form_state['link'];
}
else {
$clid = 0;
}
// Add blocks as an option for links.
$form['options_group']['ccl_type']['#options']['local_actions'] = t('Local Action');
$form['options_group']['la_title'] = array(
'#type' => 'item',
'#title' => t('Visibility settings'),
'#states' => array(
'visible' => array(
':input[name="ccl_type"]' => array(
'value' => 'local_actions',
),
),
),
);
// Visibility settings.
$form['options_group']['la'] = array(
'#type' => 'container',
'#states' => array(
'visible' => array(
':input[name="ccl_type"]' => array(
'value' => 'local_actions',
),
),
),
);
$form['options_group']['la']['#attached']['library'][] = array(
'system',
'ui.accordion',
);
$form['options_group']['la']['#attached']['js'][] = array(
'data' => '(function($){$(function() { $("#edit-la").accordion({autoHeight: false, navigation: true});})})(jQuery);',
'type' => 'inline',
);
// Per-path visibility.
$form['options_group']['la']['page_title'] = array(
'#markup' => '<h5><a href="#">' . t('Pages') . '</a></h5>',
);
$options = array(
0 => t('All pages except those listed'),
1 => t('Only the listed pages'),
);
$form['options_group']['la']['la_visibility'] = array(
'#type' => 'radios',
'#title' => t('Show link on specific pages'),
'#options' => $options,
'#default_value' => $clid && isset($link->options['la_visibility']) ? $link->options['la_visibility'] : 1,
'#prefix' => '<div>',
);
$form['options_group']['la']['la_pages'] = array(
'#type' => 'textarea',
'#default_value' => $clid && isset($link->options['la_pages']) ? $link->options['la_pages'] : '',
'#description' => t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog. %front is the front page.", array(
'%blog' => 'blog',
'%blog-wildcard' => 'blog/*',
'%front' => '<front>',
)),
'#suffix' => '</div>',
);
$form['options_group']['la']['ct_title'] = array(
'#markup' => '<h5><a href="#">' . t('Content Types') . '</a></h5>',
);
$form['options_group']['la']['la_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Show link for specific content types'),
'#default_value' => $clid && isset($link->options['la_types']) ? $link->options['la_types'] : array(),
'#options' => node_type_get_names(),
'#description' => t('Show this link only on pages that display content of the given type(s). If you select no types, there will be no type-specific limitation.'),
'#prefix' => '<div>',
'#suffix' => '</div>',
);
// Per-role visibility.
$role_options = array_map('check_plain', user_roles());
$form['options_group']['la']['roles_title'] = array(
'#markup' => '<h5><a href="#">' . t('Roles') . '</a></h5>',
);
$form['options_group']['la']['la_roles'] = array(
'#type' => 'checkboxes',
'#title' => t('Show link for specific roles'),
'#default_value' => $clid && isset($link->options['la_roles']) ? $link->options['la_roles'] : array(),
'#options' => $role_options,
'#description' => t('Show this link only for the selected role(s). If you select no roles, the link will be visible to all users.'),
'#prefix' => '<div>',
'#suffix' => '</div>',
);
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function ccl_local_actions_menu_local_tasks_alter(&$data, $router_item, $root_path) {
$user = \Drupal::currentUser();
$dest = drupal_get_destination();
$is_node = $root_path == 'node/%' ? TRUE : FALSE;
$la_cache = ccl_cache_get('ccl_local_actions');
// First narrow down the list of links that fit the visibility criteria.
foreach ($la_cache as $id => $link) {
// Check for user role restriction.
if (array_filter($link['visibility']['roles']) && !array_intersect($link['visibility']['roles'], array_keys($user->roles))) {
unset($la_cache[$id]);
continue;
}
// Check for content type restrictions.
if (array_filter($link['visibility']['types'])) {
// If this is not a node continue.
if (!$is_node) {
unset($la_cache[$id]);
continue;
}
if (!in_array($router_item['page_arguments'][0]->type, $link['visibility']['types'], TRUE)) {
unset($la_cache[$id]);
continue;
}
}
// Check for page visibility.
if ($link['visibility']['path'] == 1 && empty($link['visibility']['pages'])) {
unset($la_cache[$id]);
continue;
}
// Match path if necessary.
if ($link['visibility']['pages']) {
// Convert path to lowercase. This allows comparison of the same path
// with different case. Ex: /Page, /page, /PAGE.
$pages = \Drupal\Component\Utility\Unicode::strtolower($link['visibility']['pages']);
$path = \Drupal\Component\Utility\Unicode::strtolower(drupal_get_path_alias($_GET['q']));
// Compare the lowercase internal and lowercase path alias (if any).
$page_match = drupal_match_path($path, $pages);
if ($path != $_GET['q']) {
$page_match = $page_match || drupal_match_path($_GET['q'], $pages);
}
// When $link['visibility']['path'] has a value of 0,
// the link is displayed on all pages except those
// listed in $link['visibility']['pages'].
// When set to 1, it is displayed only on those pages
// listed in $link['visibility']['pages'].
$page_match = !($link['visibility']['path'] xor $page_match);
}
else {
$page_match = TRUE;
}
if (!$page_match) {
unset($la_cache[$id]);
}
}
// If we are on a node, we need to send it through for token replacement.
$node = $is_node ? $router_item['page_arguments'][0] : NULL;
foreach ($la_cache as $link) {
if ($processed_link = _ccl_prepare_link($link, $dest, $node)) {
// As these links are passed through a different theme function
// we have to adjust the values a bit.
$processed_link['localized_options'] = array(
'attributes' => $processed_link['attributes'],
'query' => isset($processed_link['query']) ? $processed_link['query'] : '',
'fragment' => isset($processed_link['fragment']) ? $processed_link['fragment'] : '',
);
$processed_link['localized_options']['attributes']['title'] = \Drupal\Component\Utility\Html::escape($processed_link['title']);
$data['actions']['output'][] = array(
'#theme' => 'menu_local_action',
'#link' => $processed_link,
);
$data['actions']['count']++;
}
}
}
/**
* Hook function triggered by the chache update routine of the main module.
*/
function ccl_local_actions_ccl_cache_update() {
$actions = db_query("SELECT * FROM {ccl} WHERE type = :type", array(
':type' => 'local_actions',
));
$la_cache = array();
foreach ($actions as $action) {
$action->options = unserialize($action->options);
$advanced = array();
if (isset($action->options['advanced_css'])) {
$advanced['class'] = $action->options['advanced_css'];
}
if (isset($action->options['advanced_query'])) {
$advanced['query'] = $action->options['advanced_query'];
}
if (isset($action->options['advanced_anchor'])) {
$advanced['anchor'] = $action->options['advanced_anchor'];
}
if (isset($action->options['advanced_target']) && $action->options['advanced_target'] != "default") {
$advanced['target'] = $action->options['advanced_target'];
}
if (isset($action->options['advanced_destination'])) {
$advanced['destination'] = $action->options['advanced_destination'];
}
$la_cache[] = array(
'title' => $action->title,
'href' => $action->link,
'advanced' => $advanced,
'visibility' => array(
'path' => $action->options['la_visibility'],
'pages' => $action->options['la_pages'],
'types' => $action->options['la_types'],
'roles' => $action->options['la_roles'],
),
);
}
\Drupal::cache()
->set('ccl_local_actions', $la_cache);
}
/**
* Hook function to provide link option information for the link list page.
*/
function ccl_local_actions_ccl_link_info($record) {
if ($record->type == 'local_actions') {
// @FIXME
// l() expects a Url object, created from a route name or external URI.
// $options_return = array(
// 'desc' => '',
// 'op' => l(t('Edit'), 'admin/config/user-interface/ccl/' . $record->clid . '/edit') . ' | ' . l(t('Delete'), 'admin/config/user-interface/ccl/' . $record->clid . '/delete'),
// );
$options = unserialize($record->options);
if ($options['la_visibility']) {
$options_return['desc'] = t('Only displayed on specific pages.');
}
else {
$options_return['desc'] = t('Displayed on all pages with exceptions.');
}
$clean = array_filter($options['la_types']);
if (!empty($clean)) {
$options_return['desc'] .= ' ' . t('Limited by content type.');
}
$clean = array_filter($options['la_roles']);
if (!empty($clean)) {
$options_return['desc'] .= ' ' . t('Limited by user roles.');
}
return $options_return;
}
else {
return "";
}
}
Functions
Name | Description |
---|---|
ccl_local_actions_ccl_cache_update | Hook function triggered by the chache update routine of the main module. |
ccl_local_actions_ccl_link_info | Hook function to provide link option information for the link list page. |
ccl_local_actions_form_ccl_add_form_alter | Implements hook_form_FORM_ID_alter(). |
ccl_local_actions_menu_local_tasks_alter | Implements hook_menu_local_tasks_alter(). |