You are here

ccl_actions.module in Custom Contextual Links 8

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

Implementation of core actions for CCL.

File

ccl_actions/ccl_actions.module
View source
<?php

/**
 * @file
 * Implementation of core actions for CCL.
 */

/**
 * Implements hook_menu().
 */
function ccl_actions_menu() {
  $items['admin/config/user-interface/ccl/action/add'] = array(
    'title' => 'Add new node action link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'ccl_actions_form',
    ),
    'access arguments' => array(
      'use ccl',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 10,
  );
  $items['admin/config/user-interface/ccl/action/%/edit'] = array(
    'title' => 'Edit custom link',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'ccl_actions_form',
      5,
    ),
    'access arguments' => array(
      'use ccl',
    ),
  );
  $items['admin/config/user-interface/ccl/action-trigger/%node/%/%'] = array(
    'title' => 'CCL Action Trigger',
    'page callback' => 'ccl_actions_trigger',
    'page arguments' => array(
      5,
      6,
      7,
    ),
    'access arguments' => array(
      'access contextual links',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Action link add and edit form.
 *
 * TODO:
 * - Add ability to trigger rules.
 */
function ccl_actions_form($form, &$form_state, $clid = 0) {

  // Check if we are in edit mode and load the link values.
  if ($clid) {
    $link = db_query('SELECT * FROM {ccl} WHERE clid = :clid', array(
      ':clid' => $clid,
    ))
      ->fetchObject();
    $form_state['clid'] = $clid;

    // Unserialize options.
    $link->options = unserialize($link->options);
    $node_options = $link->options['node_options'];
    if ($node_options == 'node') {
      $title = db_query('SELECT title FROM {node} WHERE nid = :nid', array(
        ':nid' => $link->options['node_id'],
      ))
        ->fetchField();
      $nid_text = $title . ' [nid:' . $link->options['node_id'] . ']';
    }
  }
  $form = array();

  // Pull in library, js and css for the form.
  $form['#attached']['library'][] = array(
    'system',
    'ui.button',
  );
  $form['#attached']['js'][] = drupal_get_path('module', 'ccl') . '/ccl.js';
  $form['#attached']['css'][] = drupal_get_path('module', 'ccl') . '/ccl.css';

  // Add an ID wrapper so that the JS and CSS from the main module take effect.
  $form['#prefix'] = '<div id="ccl-add-form">';
  $form['#suffix'] = '</div>';
  $form['action_group'] = array(
    '#type' => 'fieldset',
    '#title' => t('Node Actions'),
    '#collapsible' => TRUE,
  );
  $form['action_group']['actions_select'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Core Actions'),
    '#description' => t('Select the core actions that should become availabale.'),
    '#default_value' => $clid ? $link->options['actions_select'] : array(),
    '#options' => array(
      'publish' => t('Publish/unpublish content'),
      'sticky' => t('Make content sticky/unsticky'),
      'promote' => t('Promote/remove content from front page'),
    ),
    '#required' => TRUE,
  );
  $form['options_group'] = array(
    '#type' => 'fieldset',
    '#title' => t('Options'),
    '#collapsible' => TRUE,
  );
  $form['options_group']['node_options'] = array(
    '#type' => 'radios',
    '#title' => t('Show link for'),
    '#description' => t('Select if this link should be displayed for all nodes, all nodes of a content type or a specific node.'),
    '#options' => array(
      'node' => t('Single node'),
      'ct' => t('Content type'),
      'global' => t('All nodes'),
    ),
    '#default_value' => isset($node_options) ? $node_options : 'node',
  );

  // Load the content type names.
  $types = node_type_get_names();
  $form['options_group']['node_type'] = array(
    '#type' => 'select',
    '#title' => t('Content Type'),
    '#description' => t('The content type this link will be displayed for.'),
    '#options' => $types,
    '#default_value' => $clid ? $link->options['node_type'] : -1,
    '#states' => array(
      'visible' => array(
        ':input[name="node_options"]' => array(
          'value' => 'ct',
        ),
      ),
    ),
  );
  $form['options_group']['node_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Node ID'),
    '#description' => t('Enter the title of the node or the id of the node this link should be added to.'),
    '#size' => 40,
    '#maxlength' => 128,
    '#default_value' => isset($nid_text) ? $nid_text : '',
    '#autocomplete_path' => 'admin/config/user-interface/ccl/autocomplete',
    '#states' => array(
      'visible' => array(
        ':input[name="node_options"]' => array(
          'value' => 'node',
        ),
      ),
    ),
  );
  $form['ccl_save_link'] = array(
    '#type' => 'submit',
    '#value' => t('Save Link'),
  );
  return $form;
}

/**
 * Validafion handler for ccl_actions_form().
 *
 * @see ccl_actions_form()
 */
function ccl_actions_form_validate($form, &$form_state) {
  $values = $form_state['values'];

  // Check that that we can get the node id and transform it for saving.
  if ($values['node_options'] == 'node') {
    if (is_numeric($values['node_id'])) {
      $form_state
        ->setValueForElement($form['options_group']['node_id'], $values['node_id']);
    }
    elseif (preg_match('/\\[nid:[0-9]*\\]/', $values['node_id'], $match)) {
      $form_state
        ->setValueForElement($form['options_group']['node_id'], substr(rtrim($match[0], ']'), 5));
    }
    else {
      form_set_error('nid', t('Enter a node id or use the autocomplete widget to select an existing node.'));
    }
  }
}

/**
 * Submit handler for ccl_actions_form().
 *
 * @see ccl_actions_form()
 */
function ccl_actions_form_submit($form, &$form_state) {
  $form_state['values']['ccl_type'] = 'action';
  $selected_actions = array_filter($form_state['values']['actions_select']);
  $form_state['values']['ccl_title'] = \Drupal::translation()
    ->formatPlural(count($selected_actions), 'Action %actions', ' Actions %actions', array(
    '%actions' => implode(', ', array_keys($selected_actions)),
  ));
  $form_state['values']['ccl_link'] = '- n/a -';
  module_load_include('inc', 'ccl', 'ccl.admin');
  ccl_add_form_submit($form, $form_state);
}

/**
 * Hook function to process the contextual links element.
 */
function ccl_actions_ccl_add_link($element, $dest) {
  if (isset($element['#element']['#node']->nid)) {
    $node = $element['#element']['#node'];
    $action_cache = ccl_cache_get('ccl_actions');

    // Global elements.
    foreach ($action_cache['global'] as $id => $link) {
      _ccl_actions_prepare_link($link, $node, $element, $dest);
    }

    // Content Type.
    if (in_array($node->type, array_keys($action_cache['ct']))) {
      foreach ($action_cache['ct'][$node->type] as $id => $link) {
        _ccl_actions_prepare_link($link, $node, $element, $dest);
      }
    }

    // Individual nodes.
    if (in_array($node->nid, array_keys($action_cache['ids']))) {
      foreach ($action_cache['ids'][$node->nid] as $id => $link) {
        _ccl_actions_prepare_link($link, $node, $element, $dest);
      }
    }
  }
  return $element;
}

/**
 * Helper function to create the action link.
 *
 * This fuunctions also checks if the current user
 * has edit rights for this node.
 */
function _ccl_actions_prepare_link($actions, $node, &$element, $dest) {
  if (!node_access('update', $node)) {
    return FALSE;
  }
  foreach ($actions as $action) {
    switch ($action) {
      case 'publish':
        if ($node->status) {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/status/0',
            'title' => t('Unpublish content'),
            'query' => array(
              $dest,
            ),
          );
        }
        else {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/status/1',
            'title' => t('Publish content'),
            'query' => array(
              $dest,
            ),
          );
        }
        $element['#links']['ccl-action-status-' . $node->nid] = $link;
        break;
      case 'sticky':
        if ($node->sticky) {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/sticky/0',
            'title' => t('Make content unsticky'),
            'query' => array(
              $dest,
            ),
          );
        }
        else {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/sticky/1',
            'title' => t('Make content sticky'),
            'query' => array(
              $dest,
            ),
          );
        }
        $element['#links']['ccl-action-sticky-' . $node->nid] = $link;
        break;
      case 'promote':
        if ($node->promote) {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/promote/0',
            'title' => t('Remove content from front page'),
            'query' => array(
              $dest,
            ),
          );
        }
        else {
          $link = array(
            'href' => 'admin/config/user-interface/ccl/action-trigger/' . $node->nid . '/promote/1',
            'title' => t('Promote content to front page'),
            'query' => array(
              $dest,
            ),
          );
        }
        $element['#links']['ccl-action-promote-' . $node->nid] = $link;
        break;
    }
  }
}

/**
 * Trigger function to execute actions.
 */
function ccl_actions_trigger($node, $action, $state) {
  if (!node_access('update', $node)) {
    drupal_set_message(t('You have no permission to update %node_title.', array(
      '%node_title' => $node->title,
    )), 'error');
    drupal_goto();
  }
  switch ($action) {
    case 'status':
      if ($state) {
        actions_do('node_publish_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been published.', array(
          '%node_title' => $node->title,
        )));
      }
      else {
        $res = actions_do('node_unpublish_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been unpublished.', array(
          '%node_title' => $node->title,
        )));
      }
      break;
    case 'sticky':
      if ($state) {
        actions_do('node_make_sticky_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been made sticky.', array(
          '%node_title' => $node->title,
        )));
      }
      else {
        $res = actions_do('node_make_unsticky_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been made unsticky.', array(
          '%node_title' => $node->title,
        )));
      }
      break;
    case 'promote':
      if ($state) {
        actions_do('node_promote_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been promoted to front page.', array(
          '%node_title' => $node->title,
        )));
      }
      else {
        $res = actions_do('node_unpromote_action', $node);
        $node
          ->save();
        drupal_set_message(t('%node_title has been removed from front page.', array(
          '%node_title' => $node->title,
        )));
      }
      break;
  }

  // Return to set destination parameter.
  drupal_goto();
}

/**
 * Hook function to provide link option information for the link list page.
 */
function ccl_actions_ccl_link_info($record) {
  if ($record->type == 'action') {

    // Get content type names.
    $cts = node_type_get_names();

    // @FIXME
    // l() expects a Url object, created from a route name or external URI.
    // $options_return['op'] = l(t('Edit'), 'admin/config/user-interface/ccl/action/' . $record->clid . '/edit') . ' | ' . l(t('Delete'), 'admin/config/user-interface/ccl/' . $record->clid . '/delete');
    $options = unserialize($record->options);
    switch ($options['node_options']) {
      case 'global':
        $options_return['desc'] = t('Attached to all nodes.');
        break;
      case 'ct':
        $options_return['desc'] = t('Attached to all nodes of the content type %ct.', array(
          '%ct' => $cts[$options['node_type']],
        ));
        break;
      case 'node':
        $node_title = db_query('SELECT title FROM {node} WHERE nid = :nid', array(
          ':nid' => $options['node_id'],
        ))
          ->fetchField();
        $options_return['desc'] = t('Attached to %node_title [NID: !nid].', array(
          '%node_title' => $node_title,
          '!nid' => $options['node_id'],
        ));
        break;
    }
    return $options_return;
  }
  else {
    return "";
  }
}

/**
 * Hook function triggered by the chache update routine of the main module.
 */
function ccl_actions_ccl_cache_update() {
  $actions = db_query("SELECT * FROM {ccl} WHERE type = :type", array(
    ':type' => 'action',
  ));
  $actions_cache = array(
    'global' => array(),
    'ct' => array(),
    'ids' => array(),
  );
  foreach ($actions as $action) {
    $action->options = unserialize($action->options);
    $filtered_actions = array_keys(array_filter($action->options['actions_select']));
    if ($action->options['node_options'] == 'global') {
      $actions_cache['global'][] = $filtered_actions;
    }
    elseif ($action->options['node_options'] == 'node') {
      $actions_cache['ids'][$action->options['node_id']][] = $filtered_actions;
    }
    else {
      $actions_cache['ct'][$action->options['node_type']][] = $filtered_actions;
    }
  }
  \Drupal::cache()
    ->set('ccl_actions', $actions_cache);
}

Functions

Namesort descending Description
ccl_actions_ccl_add_link Hook function to process the contextual links element.
ccl_actions_ccl_cache_update Hook function triggered by the chache update routine of the main module.
ccl_actions_ccl_link_info Hook function to provide link option information for the link list page.
ccl_actions_form Action link add and edit form.
ccl_actions_form_submit Submit handler for ccl_actions_form().
ccl_actions_form_validate Validafion handler for ccl_actions_form().
ccl_actions_menu Implements hook_menu().
ccl_actions_trigger Trigger function to execute actions.
_ccl_actions_prepare_link Helper function to create the action link.