You are here

replicate_ui.module in Replicate UI 7

Same filename and directory in other branches
  1. 8 replicate_ui.module

Provide a user interface for the Replicate API.

File

replicate_ui.module
View source
<?php

/**
 * @file
 * Provide a user interface for the Replicate API.
 */

/**
 * Implements hook_help().
 */
function replicate_ui_help($path, $arg) {
  switch ($path) {

    // Main module page.
    case 'admin/help#replicate_ui':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('This module provides user interface integration for the simple yet powerful Replicate API.') . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('This module provides integration with Drupal actions which means that you can start to replicate things via the user interfaces with built in support for:') . '</dt>';
      $output .= '<dd>' . t('Drupal core nodes') . '</dd>';
      $output .= '<dd>' . t('Drupal core actions') . '</dd>';
      $output .= '<dd>' . t('"Any" Drupal Entity available to <a href="!entityapi">Entity API</a> (see hook_menu)', array(
        '!entityapi' => 'https://www.drupal.org/project/entity',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!views">Views</a>', array(
        '!views' => 'https://www.drupal.org/project/views',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!vbo">Views Bulk Operations</a>', array(
        '!vbo' => 'https://www.drupal.org/project/Views_bulk_operations',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!rules">Rules</a>', array(
        '!rules' => 'https://www.drupal.org/project/rules',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!fc">Field Collection</a>', array(
        '!fc' => 'https://www.drupal.org/project/field_collection',
      )) . '</dd>';
      $output .= '<dt>' . t('Other Replicate modules:') . '</dt>';
      $output .= '<dd>' . t('<a href="!rfc">Replicate Field Collection</a>', array(
        '!rfc' => 'https://www.drupal.org/project/replicate_field_collection',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!rc">Replicate Commerce</a>', array(
        '!rc' => 'https://www.drupal.org/project/replicate_commerce',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!rb">Replicate Bean</a>', array(
        '!rb' => 'https://www.drupal.org/project/replicate_bean',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!re">Replicate Entityform</a>', array(
        '!re' => 'https://www.drupal.org/project/replicate_entityform',
      )) . '</dd>';
      $output .= '<dd>' . t('<a href="!ru">Replicate User</a>', array(
        '!ru' => 'https://www.drupal.org/project/replicate_user',
      )) . '</dd>';
      return $output;
  }
}

/**
 * Implements hook_menu().
 */
function replicate_ui_menu() {
  $items['replicate/%/%'] = array(
    'title' => 'Replicate',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'replicate_ui_confirm',
      1,
      2,
    ),
    'access callback' => 'replicate_ui_access',
    'access arguments' => array(
      1,
      2,
    ),
  );
  $items['node/%node/replicate'] = array(
    'title' => 'Replicate',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'replicate_ui_confirm',
      0,
      1,
    ),
    'access callback' => 'replicate_ui_access',
    'access arguments' => array(
      0,
      1,
    ),
    'type' => MENU_LOCAL_TASK,
  );

  // support for user entity though this might not do what you think without
  // some kind of clean up module: see https://www.drupal.org/node/2394779
  $items['user/%user/replicate'] = array(
    'title' => 'Replicate',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'replicate_ui_confirm',
      0,
      1,
    ),
    'access callback' => 'replicate_ui_access',
    'access arguments' => array(
      0,
      1,
    ),
    'type' => MENU_LOCAL_TASK,
  );

  // ewwwww, taxonomy support
  if (module_exists('taxonomy')) {
    $items['taxonomy/term/%taxonomy_term/replicate'] = array(
      'title' => 'Replicate',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'replicate_ui_confirm',
        'taxonomy_term',
        2,
      ),
      'access callback' => 'replicate_ui_access',
      'access arguments' => array(
        'taxonomy_term',
        2,
      ),
      'type' => MENU_LOCAL_TASK,
    );
  }

  // optional support based on modules being installed
  // entityform support, we don't check for the submodule directly because
  // people might want to use another, completely valid, approach
  if (module_exists('entityform')) {
    $items['entityform/%entityform/replicate'] = array(
      'title' => 'Replicate',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'replicate_ui_confirm',
        0,
        1,
      ),
      'access callback' => 'replicate_ui_access',
      'access arguments' => array(
        0,
        1,
      ),
      'type' => MENU_LOCAL_TASK,
    );
  }

  // field_collection support, we don't check for the submodule directly
  // because people might want to use another, completely valid, approach
  if (module_exists('field_collection')) {

    // Add menu paths for viewing/editing/deleting field collection items.
    foreach (field_info_fields() as $field) {
      if ($field['type'] == 'field_collection') {
        $path = field_collection_field_get_path($field);
        $items[$path . '/%field_collection_item/replicate'] = array(
          'title' => 'Replicate',
          'page callback' => 'drupal_get_form',
          'page arguments' => array(
            'replicate_ui_confirm',
            'field_collection_item',
            2,
          ),
          'access callback' => 'replicate_ui_access',
          'access arguments' => array(
            'field_collection_item',
            2,
          ),
          'type' => MENU_LOCAL_TASK,
          'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
        );
      }
    }
  }
  return $items;
}

/**
 * Access control for access to replicate.
 */
function replicate_ui_access($type, $etid) {
  if (is_object($etid)) {
    $info = entity_get_info($type);

    // ensure we had a valid entity type or bail early
    if (!isset($info['entity keys']) || !isset($info['entity keys']['id'])) {
      return FALSE;
    }
    $etid = $etid->{$info['entity keys']['id']};
  }
  $access = FALSE;

  // make sure they can create this item and access replicate
  $entity = entity_load_single($type, $etid);

  // ensure this exists, they have access to see and create the type and access the ui
  if (!empty($entity) && entity_access('view', $type, $entity) && entity_access('create', $type, $entity) && user_access('replicate entities')) {
    $access = TRUE;
  }

  // Allow other modules to check this access.
  drupal_alter('replicate_ui_access_check', $access, $type, $entity);
  return $access;
}

/**
 * Menu callback.  Ask for confirmation of replication.
 */
function replicate_ui_confirm($form, &$form_state, $type, $entity_id) {

  // convert from object to id if we got an object instead
  if (is_object($entity_id)) {
    $info = entity_get_info($type);
    $entity_id = $entity_id->{$info['entity keys']['id']};
  }

  // write id / type into form to pass to the submit handler
  $form['entity_id'] = array(
    '#type' => 'value',
    '#value' => $entity_id,
  );
  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $type,
  );
  return confirm_form($form, t('Are you sure you want to replicate %type entity id %id?', array(
    '%type' => $type,
    '%id' => $entity_id,
  )), '', t('This action cannot be undone.'), t('Replicate'), t('Cancel'));
}

/**
 * Confirm submission.
 */
function replicate_ui_confirm_submit($form, &$form_state) {
  if ($form_state['values']['confirm']) {
    $entity_type = $form_state['values']['entity_type'];
    $entity_id = $form_state['values']['entity_id'];

    // special case for field collection
    if ($entity_type == 'field_collection_item') {
      $entity = entity_load_single($entity_type, $entity_id);
      $new = replicate_clone_entity('field_collection_item', $entity);
      $new
        ->setHostEntity($entity
        ->hostEntityType(), $entity
        ->hostEntity());
      $new
        ->save();
      $path = 'field-collection/' . str_replace('_', '-', $new->field_name) . '/' . $new->item_id;
      $id = $new->item_id;
    }
    else {

      // load entity for replicate
      $id = replicate_entity_by_id($entity_type, $entity_id);
      $entities = entity_load($entity_type, array(
        $id,
      ));
      $entity_uri = entity_uri($entity_type, $entities[$id]);
      $path = $entity_uri['path'];
    }
    if ($id) {

      // Add replica id/type to form state.
      $form_state['replica_id'] = $id;
      $form_state['replica_type'] = $entity_type;

      // redirect to the new item
      drupal_set_message(t('%type (%id) has been replicated to id %new!', array(
        '%type' => $entity_type,
        '%id' => $entity_id,
        '%new' => $id,
      )));
      $form_state['redirect'] = $path;
      if (module_exists('rules')) {

        // Rules needs the entity in a wrapper, since we don't know beforehand
        // what type of entity we have.
        $original = entity_load_single($entity_type, $entity_id);
        $original_wrapped = entity_metadata_wrapper($entity_type, $original);
        $replica = entity_load_single($entity_type, $id);
        $replica_wrapped = entity_metadata_wrapper($entity_type, $replica);
        rules_invoke_event('replicate_ui_after_replication', $replica_wrapped, $entity_type, $original_wrapped);
      }
    }
  }
}

/**
 * Implements hook_permission().
 */
function replicate_ui_permission() {
  return array(
    'replicate entities' => array(
      'title' => t('Replicate entities via UI'),
      'description' => t('Makes the replicate / duplicate functionality available via the UI. Still requires Create permissions on an entity to display.'),
    ),
  );
}

/**
 * Implements hook_views_api().
 */
function replicate_ui_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'replicate_ui') . '/views',
  );
}

/**
 * Implements hook_action_info().
 *
 * Registers custom replicate actions as Drupal actions.
 */
function replicate_ui_action_info() {
  $actions = array();
  $files = replicate_ui_load_action_includes();
  foreach ($files as $filename) {
    $action_info_fn = 'replicate_ui_' . str_replace('.', '_', basename($filename, '.inc')) . '_info';
    $action_info = call_user_func($action_info_fn);
    if (is_array($action_info)) {
      $actions += $action_info;
    }
  }
  return $actions;
}

/**
 * Loads the replicate actions placed in their own include files
 *
 * @return
 *   An array of containing filenames of the included actions.
 */
function replicate_ui_load_action_includes() {
  static $loaded = FALSE;

  // The list of replicate actions is fairly static, so it's hardcoded for better
  // performance (hitting the filesystem with file_scan_directory(), and then
  // caching the result has its cost).
  $path = drupal_get_path('module', 'replicate_ui') . '/actions/';
  $files = array(
    'replicate.action.inc',
  );
  if (!$loaded) {
    foreach ($files as $file) {
      include_once $path . $file;
    }
    $loaded = TRUE;
  }
  return $files;
}

/**
 * Implements hook_admin_paths().
 */
function replicate_ui_admin_paths() {
  $paths = array(
    'replicate/*/*' => TRUE,
    'node/*/replicate' => TRUE,
    'field-collection/*/*/replicate' => TRUE,
  );
  return $paths;
}

Functions

Namesort descending Description
replicate_ui_access Access control for access to replicate.
replicate_ui_action_info Implements hook_action_info().
replicate_ui_admin_paths Implements hook_admin_paths().
replicate_ui_confirm Menu callback. Ask for confirmation of replication.
replicate_ui_confirm_submit Confirm submission.
replicate_ui_help Implements hook_help().
replicate_ui_load_action_includes Loads the replicate actions placed in their own include files
replicate_ui_menu Implements hook_menu().
replicate_ui_permission Implements hook_permission().
replicate_ui_views_api Implements hook_views_api().