You are here

formassembly.module in FormAssembly 7

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

Contains hooks implementations and callbacks to non-admin pages.

File

formassembly.module
View source
<?php

/**
 * @file
 * Contains hooks implementations and callbacks to non-admin pages.
 */
const FA_URI_ARGUMENT_POS = 1;
function formassembly_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'formassembly') . '/includes/views',
  );
}

/**
 * Implements hook_entity_info().
 */
function formassembly_entity_info() {
  return array(
    'fa_form' => array(
      'label' => t('FormAssembly Form'),
      'plural label' => t('FormAssembly Forms'),
      'base table' => 'formassembly',
      'entity keys' => array(
        'id' => 'eid',
      ),
      'fieldable' => TRUE,
      'entity class' => 'FormAssemblyEntity',
      'controller class' => 'FormAssemblyEntityController',
      'module' => 'formassembly',
      'load hook' => 'formassembly_load',
      'label callback' => 'entity_class_label',
      'uri callback' => 'entity_class_uri',
      'access callback' => 'formassembly_access',
      'view modes' => array(
        'markup' => array(
          'label' => t('FormAssembly Markup'),
          'custom settings' => FALSE,
        ),
        'full' => array(
          'label' => t('Full Page View'),
          'custom settings' => FALSE,
        ),
      ),
    ),
  );
}

/**
 * Implements hook_entity_property_info_alter().
 */
function formassembly_entity_property_info_alter(&$info) {
  $properties =& $info['fa_form']['properties'];
  $properties['modified'] = array(
    'label' => t("Date changed"),
    'type' => 'date',
    'schema field' => 'modified',
    'description' => t("The date the external data of the entity was last updated."),
  );
}

/***********************/

/* Basic API functions */

/***********************/

/**
 * Load a single fa_form entity.
 *
 * @param int $eid
 *   The unique Drupal entity ID
 *
 * @param bool $reset
 *   Flag to reset cache
 *
 * @return FormAssemblyEntity
 *   The return value is either a FormAssembly Entity or FALSE
 */
function formassembly_load($eid, $reset = FALSE) {
  $form = formassembly_load_multiple(array(
    $eid,
  ), $reset);
  if (isset($form[$eid])) {
    return $form[$eid];
  }
  else {
    return FALSE;
  }
}

/**
 * Load multiple fa_form entities.
 *
 * @param array $eids
 *   An array of Drupal entity IDs
 *
 * @param bool $reset
 *   Flag to reset cache
 *
 * @return array
 *   An array of fa_form entities keyed by ID
 */
function formassembly_load_multiple($eids = array(), $reset = FALSE) {
  if ($reset) {
    entity_get_controller('fa_form')
      ->resetCache();
  }
  return entity_get_controller('fa_form')
    ->load($eids);
}

/**
 * Save a form.
 *
 * @param FormAssemblyEntity $form
 *   An fa_form entity to save.
 */
function formassembly_save($form) {
  entity_get_controller('fa_form')
    ->save($form);
}

/**
 * Delete single form.
 *
 * @param int $eid
 *   The unique Drupal entity ID
 */
function formassembly_delete($eid) {
  formassembly_delete_multiple(array(
    $eid,
  ));
}

/**
 * Delete multiple forms.
 *
 * @param array $eids
 *   An array of Drupal entity IDs.
 */
function formassembly_delete_multiple($eids) {
  entity_get_controller('fa_form')
    ->delete($eids);
}

/**
 * Implements hook_menu().
 *
 * @todo View/Edit tabs not working yet
 */
function formassembly_menu() {
  $items = array();
  $items['admin/config/services/formassembly'] = array(
    'title' => 'FormAssembly',
    'description' => 'Configure authentication and options for FormAssembly integration.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'formassembly_settings_form',
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer formassembly',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'formassembly.admin.inc',
  );
  $items['admin/config/services/formassembly/authorize'] = array(
    'title' => 'FormAssembly OAuth Authorization',
    'page callback' => 'formassembly_oauth_authorization_callback',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer formassembly',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'formassembly.admin.inc',
  );
  $items['formassembly/%formassembly'] = array(
    'title' => 'View',
    'page callback' => 'formassembly_view',
    'page arguments' => array(
      FA_URI_ARGUMENT_POS,
    ),
    'access arguments' => array(
      'view formassembly',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items['formassembly/%formassembly/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'formassembly_edit',
    'page arguments' => array(
      'formassembly_form',
      FA_URI_ARGUMENT_POS,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer formassembly',
    ),
    'type' => MENU_LOCAL_TASK,
    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
  );
  $items['admin/structure/formassembly'] = array(
    'title' => 'FormAssembly Forms',
    'description' => 'Manage pre-fill parameters used with FormAssembly forms.',
    'page callback' => 'formassembly_build_list',
    'access arguments' => array(
      'administer formassembly',
    ),
    'file' => 'formassembly.admin.inc',
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * The fa_form view callback.
 *
 * @param FormAssemblyEntity $fa_form
 *   An fa_form entity
 *
 * @param string $view_mode
 *   The view mode to display
 *
 * @return array
 *   Returns the render array for an fa_form entity.
 */
function formassembly_view($fa_form, $view_mode = 'full') {
  switch ($view_mode) {
    case 'full':
      drupal_set_title(entity_label('fa_form', $fa_form));
      return entity_view('fa_form', array(
        entity_id('fa_form', $fa_form) => $fa_form,
      ), 'full');
    case 'markup':
      return entity_view('fa_form', array(
        entity_id('fa_form', $fa_form) => $fa_form,
      ), 'markup');
  }
}

/**
 * Implements hook_theme().
 */
function formassembly_theme($existing, $type, $theme, $path) {
  return array(
    'fa_form__fa_form' => array(
      'template' => 'fa_form__fa_form__markup',
      'base hook' => 'entity',
      'path' => drupal_get_path('module', 'formassembly'),
    ),
  );
}

/**
 * Implements hook_permission().
 */
function formassembly_permission() {
  $return = array();
  $return['administer formassembly'] = array(
    'title' => t('Administer FormAssembly'),
    'description' => t("Make requests against FormAssembly's API and sync forms"),
  );
  $return['view formassembly'] = array(
    'title' => t('View FormAssembly Forms'),
    'description' => t('View an imported FromAssembly Form'),
  );
  $return['reference formassembly'] = array(
    'title' => t('Reference FormAssembly Forms'),
    'description' => t('Select FromAssembly Forms to embed via Entity Reference fields'),
  );
  return $return;
}

/**
 * Implements hook_field_access().
 */
function formassembly_field_access($op, $field, $entity_type, $entity, $account) {

  // We are only interested in controlling edit mode on Entity Reference
  // fields that target Form Assembly entities...
  if ($op == 'edit' && $field['type'] == 'entityreference' && $field['settings']['target_type'] == 'fa_form') {
    return user_access('reference formassembly');
  }
}

/**
 * Callback that executes when the user returns after authorizing the app.
 */
function formassembly_oauth_authorization_callback() {
  if (!empty($_GET['code'])) {
    $client_id = variable_get('formassembly_oauth_cid', '');
    $client_secret = variable_get('formassembly_oauth_secret', '');
    $request = new FormAssemblyRequest($client_id, $client_secret);
    if ($request
      ->getToken($_GET['code'])) {
      drupal_set_message(t('Authorization Successful'));
      watchdog('formassembly', 'OAuth authorization successful.', array(), WATCHDOG_NOTICE);
    }
    else {
      drupal_set_message(t('Authorization Failed'), 'error');
      watchdog('formassembly', 'OAuth authorization failed.', array(), WATCHDOG_ERROR);
    }
  }

  // Redirect back to the settings form.
  drupal_goto('admin/config/services/formassembly');
}

/**
 * Access callback for fa_forms.
 */
function formassembly_access($op, $form, $account = NULL) {
  global $user;
  if (!isset($account)) {
    $account = $user;
  }
  switch ($op) {
    case 'create':
      return user_access('administer formassembly', $account);
    case 'view':
      return user_access('administer formassembly', $account) || user_access('view formassembly', $account);
    case 'edit':
      return user_access('administer formassembly');
  }
}

/**
 * Implementation of callback_batch_operation()
 *
 * Callback function: first batch operation to sync with FormAssembly
 *
 * @param bool $use_admin
 *   Is the admin index in use?
 * @param $context
 *   Required batch context array
 */
function formassembly_batch_get_forms($use_admin = false, &$context) {
  if (empty($context['sandbox'])) {

    // Batch has not run before.  Initialize
    $client_id = variable_get('formassembly_oauth_cid', '');
    $client_secret = variable_get('formassembly_oauth_secret', '');
    $request = new FormAssemblyRequest($client_id, $client_secret);
    $token = $request
      ->getToken();
    if ($token) {
      $request
        ->setToken($token);
    }
    else {
      watchdog('formassembly', 'Could not initialize batch.', array(), WATCHDOG_ERROR);
    }
  }
  else {

    // Batch has started processing.  Get the request back from context.
    $request = $context['sandbox']['request'];
  }
  try {

    //$use_admin = variable_get('formassembly_admin_index', FALSE);
    if ($use_admin) {
      $context['message'] = t('Now requesting admin index page %page', array(
        '%page' => $request
          ->getPage(),
      ));
      if ($request
        ->getForms('admin/api_v1/forms/index.json', $use_admin)) {

        //returns true when finished
        $context['finished'] = 1;
      }
      else {
        $context['finished'] = 0.66;
        $context['sandbox']['request'] = $request;
      }
    }
    else {
      if ($request
        ->getForms()) {
        $context['finished'] = 1;
      }
    }
    $context['results']['request'] = $request;
  } catch (Exception $caught) {
    watchdog('formassembly', 'Form form batch request failed. Error message: @message', array(
      '@message' => $caught
        ->getMessage(),
    ), WATCHDOG_ERROR);
  }
}

/**
 * Implementation of callback_batch_operation()
 *
 * Callback function: second batch operation to sync with FormAssembly
 * @param $context
 *   Required batch context array
 */
function formassembly_batch_extract_forms(&$context) {
  if (!empty($context['results']['request'])) {
    $context['finished'] = 0.99;
    $context['message'] = t('Processing FormAssembly Responses');
    $context['results']['request']
      ->processResponses();
    $context['finished'] = 1;
  }
}

/**
 * Implementation of  callback_batch_finished()
 * @param $success
 * @param $results
 * @param $operations
 */
function formassembly_batch_get_finished($success, $results, $operations) {
  $request = $results['request'];
  if ($request instanceof FormAssemblyRequest) {
    $request
      ->syncForms();
  }
}

/**
 * Form definition for editing a fa_form entity.
 */
function formassembly_form($form, &$form_state, $fa_form = NULL) {

  // attach fa_query_param field
  field_attach_form('fa_form', $fa_form, $form, $form_state);
  $form['fa_query_params']['#weight'] = 10;

  // Baseline token replacement functionality is available in core, but display
  // the token insert list from the token module if installed.
  if (module_exists('token')) {
    $form['token_tree'] = array(
      '#type' => 'fieldset',
      '#title' => t('Replacement tokens'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#theme' => 'token_tree',
    );
  }
  else {
    $form['token_tree'] = array(
      '#markup' => '<p>' . t('Enable the <a href="@drupal-token">Token module</a> to view the available token browser.', array(
        '@drupal-token' => 'http://drupal.org/project/token',
      )) . '</p>',
    );
  }
  $form['token_tree']['#weight'] = 20;
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#weight' => 50,
  );
  $form['fa_form'] = array(
    '#type' => 'value',
    '#value' => $fa_form,
    '#weight' => 70,
  );

  // get the form html
  $form_array = formassembly_view($fa_form, 'markup');

  //there should only be one form
  $form_array = array_pop($form_array['fa_form']);
  $form_html = $form_array['fa_markup']['#markup'];
  $rows = array();
  $header = array(
    t('Element ID'),
    t('Associated Label'),
    t('HTML tag'),
    t('Attribute: type'),
    t('Attribute: value'),
  );
  $dom = new DOMDocument();
  libxml_use_internal_errors(TRUE);
  if (!$dom
    ->loadHTML($form_html)) {
    foreach (libxml_get_errors() as $error) {
      watchdog('FormAssembly', 'Form HTML failed to load on edit tab. LibXML error message is: ' . $error->message, WATCHDOG_ERROR, NULL);
    }
    libxml_clear_errors();
  }
  $label_elements = $dom
    ->getElementsByTagName('label');
  foreach ($label_elements as $label) {

    //FormAssembly label ids are of the form tfa_N-L where tfa_N is the id of the element
    $associated_id = rtrim($label
      ->getAttribute('id'), '-L');
    $associated_element = $dom
      ->getElementById($associated_id);
    $rows[]['data'] = array(
      check_plain($associated_id),
      check_plain($label->nodeValue),
      check_plain($associated_element->tagName),
      check_plain($associated_element
        ->getAttribute('type')),
      check_plain($associated_element
        ->getAttribute('value')),
    );
  }
  $form['structure'] = array(
    '#type' => 'item',
    '#markup' => theme('table', array(
      'header' => $header,
      'rows' => $rows,
    )),
    '#weight' => 80,
  );

  // format serialized query parameters array as "key|value" string for editing
  $value =& $form['fa_query_params'][LANGUAGE_NONE][0]['value']['#default_value'];
  if ($value) {
    $value = list_allowed_values_string(unserialize($value));
  }
  return $form;
}

/**
 * Submit handler for the fa_form entity form.
 *
 * @param $form
 * @param $form_state
 */
function formassembly_form_submit($form, &$form_state) {

  // Turn user entered key|value pairs into serialized array.
  $value =& $form_state['values']['fa_query_params']['und'][0]['value'];
  $value = serialize(list_extract_allowed_values($value, 'list_text', FALSE));
  $entity = $form_state['values']['fa_form'];
  field_attach_submit('fa_form', $entity, $form, $form_state);
  entity_get_controller('fa_form')
    ->save($entity);
  drupal_set_message(t('Form <em>@name</em> has been saved.', array(
    '@name' => $entity->name,
  )));
  $form_state['redirect'] = 'formassembly/' . $entity->eid;
}

/**
 * Menu callback; presents the fa_form edit form.
 *
 * @param $callback
 * @param $fa_form
 * @return array|mixed
 */
function formassembly_edit($callback, $fa_form) {
  drupal_set_title(t('<em>Edit configuration: </em> \'@title\'', array(
    '@title' => $fa_form->name,
  )), PASS_THROUGH);
  return drupal_get_form($callback, $fa_form);
}

Functions

Namesort descending Description
formassembly_access Access callback for fa_forms.
formassembly_batch_extract_forms Implementation of callback_batch_operation()
formassembly_batch_get_finished Implementation of callback_batch_finished()
formassembly_batch_get_forms Implementation of callback_batch_operation()
formassembly_delete Delete single form.
formassembly_delete_multiple Delete multiple forms.
formassembly_edit Menu callback; presents the fa_form edit form.
formassembly_entity_info Implements hook_entity_info().
formassembly_entity_property_info_alter Implements hook_entity_property_info_alter().
formassembly_field_access Implements hook_field_access().
formassembly_form Form definition for editing a fa_form entity.
formassembly_form_submit Submit handler for the fa_form entity form.
formassembly_load Load a single fa_form entity.
formassembly_load_multiple Load multiple fa_form entities.
formassembly_menu Implements hook_menu().
formassembly_oauth_authorization_callback Callback that executes when the user returns after authorizing the app.
formassembly_permission Implements hook_permission().
formassembly_save Save a form.
formassembly_theme Implements hook_theme().
formassembly_view The fa_form view callback.
formassembly_views_api

Constants

Namesort descending Description
FA_URI_ARGUMENT_POS @file Contains hooks implementations and callbacks to non-admin pages.