You are here

ccl_local_actions.module in Custom Contextual Links 8

Same filename and directory in other branches
  1. 7 ccl_local_actions/ccl_local_actions.module

Adds the ability to create local tasks with CCL.

File

ccl_local_actions/ccl_local_actions.module
View 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

Namesort descending 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().