You are here

rules_forms.module in Rules Forms Support 7.2

Same filename and directory in other branches
  1. 7 rules_forms.module

Rules Forms Support provides events, conditions, and actions for site forms.

File

rules_forms.module
View source
<?php

/**
 * @file
 * Rules Forms Support provides events, conditions, and actions for site forms.
 */
define('RULES_FORMS_ADMIN_PATH', 'admin/config/workflow/rules/forms');

/**
 * Implements hook_help().
 */
function rules_forms_help($path, $arg) {
  switch ($path) {
    case 'admin/help#rules_forms':
      return '<p>' . t('Rules Forms Support provides Rules events, conditions, and actions for any form built with the Drupal form API. To activate events for a form you must first visit <a href="!admin">Rules Forms settings</a> and enable activation messages.', array(
        '!admin' => url(RULES_FORMS_ADMIN_PATH),
      )) . '</p>';
    case RULES_FORMS_ADMIN_PATH:
      return '<p>' . t('Settings and overview of form events and active elements.') . '</p>';
  }
}

/**
 * Implements hook_permission().
 */
function rules_forms_permission() {
  return array(
    'administer rules forms rules' => array(
      'title' => t('Administer Rules Forms rules'),
      'description' => t('Grants access to building rules for forms.'),
    ),
    'administer rules forms' => array(
      'title' => t('Administer Rules Forms'),
      'description' => t('Grants access to Rules Forms settings and activating or deactivating rules for forms.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function rules_forms_menu() {

  // Keep track of what would be the last argument number offset for
  // RULES_FORMS_ADMIN_PATH when used as page/access arguments.
  $arguments_offset = count(explode('/', RULES_FORMS_ADMIN_PATH)) - 1;
  $items = array();
  $items[RULES_FORMS_ADMIN_PATH] = array(
    'title' => 'Forms Support',
    'description' => 'Manage Rules Forms events, forms, and form element information.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'rules_forms_admin_events',
    ),
    'access arguments' => array(
      'administer rules forms',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'includes/rules_forms.admin.inc',
  );
  $items[RULES_FORMS_ADMIN_PATH . '/%/activate/%'] = array(
    'title' => 'Activate events for a form',
    'type' => MENU_CALLBACK,
    'page callback' => 'rules_forms_activate',
    'page arguments' => array(
      $arguments_offset + 1,
      $arguments_offset + 3,
    ),
    'access arguments' => array(
      'administer rules forms',
    ),
    'file' => 'includes/rules_forms.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_hook_info().
 */
function rules_forms_hook_info() {
  $hooks['rules_forms_element_info'] = array(
    'group' => 'info',
  );
  $hooks['rules_forms_element_info_alter'] = array(
    'group' => 'info',
  );
  return $hooks;
}

/**
 * Returns cached data.
 *
 * @param string $cid
 *   The cache ID of the cache to return.
 */
function &rules_forms_get_cache($cid) {
  static $cache;
  if (!isset($cache)) {
    $cache =& drupal_static(__FUNCTION__, array());
  }
  if (!isset($cache[$cid])) {
    if ($cache_data = cache_get($cid)) {
      $cache[$cid] = $cache_data->data;
    }
    else {
      $cache[$cid] = FALSE;
    }
  }
  return $cache[$cid];
}

/**
 * Caches data.
 *
 * @param string $cid
 *   The cache ID.
 * @param mixed $data
 *   The data to be cached.
 */
function rules_forms_set_cache($cid, $data) {
  $cache =& drupal_static('rules_forms_get_cache', array());
  $cache[$cid] = $data;
  cache_set($cid, $cache[$cid]);
}

/**
 * Clears the Rules Forms and Rules caches.
 */
function rules_forms_clear_cache() {
  cache_clear_all('rules_forms', 'cache', TRUE);
  rules_clear_cache();
  drupal_static_reset('rules_forms_get_cache');
}

/**
 * Implements hook_flush_caches().
 */
function rules_forms_flush_caches() {
  db_update('rules_forms')
    ->fields(array(
    'rebuild' => 1,
  ))
    ->execute();
}

/**
 * Creates a data structure (array).
 */
function rules_forms_create_structure() {
  return array();
}

/**
 * Implements hook_form_alter().
 */
function rules_forms_form_alter(&$form, &$form_state, $form_id) {
  if (rules_forms_get_form_info($form_id)) {

    // Set elements for form events.
    rules_forms_event_build($form, $form_state, $form_id);
    $form['#validate'][] = 'rules_forms_event_validate';
    $form['#submit'][] = 'rules_forms_event_submit';
    $form['#after_build'][] = 'rules_forms_after_build';

    // @TODO Add button level validate/submit handlers.
  }
  elseif (!empty($_SESSION['rules_forms_message'])) {

    // Display form ID message if enabled for this session.
    $uri = drupal_get_destination();
    $link = l($form_id, RULES_FORMS_ADMIN_PATH . '/' . $form_id . '/activate/' . urlencode(trim($uri['destination'], '/')));
    $msg = t('Activate events for !form.', array(
      '!form' => $link,
    ));
    drupal_set_message($msg, 'status', FALSE);
  }
}

/**
 * Form build handler. Stores form values and invokes the event.
 */
function rules_forms_event_build(&$form, &$form_state, $form_id) {

  // @TODO Save form values on build for comparison against
  // the form_state entity on validate and submit events.
  rules_forms_invoke_event('form_built', $form, $form_state, $form_id);
}

/**
 * Validation handler to invoke "form validate" events.
 *
 * @see rules_forms_form_alter()
 */
function rules_forms_event_validate(&$form, &$form_state) {
  rules_forms_invoke_event('form_validate', $form, $form_state);
}

/**
 * Submit handler to invoke "form submitted" events.
 *
 * @see rules_forms_form_alter()
 */
function rules_forms_event_submit(&$form, &$form_state) {
  rules_forms_invoke_event('form_submit', $form, $form_state);
}

/**
 * Invoke rules event of a certain type.
 *
 * @param string $event_type
 *   Possible values:
 *   - form_built
 *   - form_validate
 *   - form_submit
 *   - button_ELEMENT_ID_validate
 *   - button_ELEMENT_ID_submit
 *   The type of Rules Forms event being invoked.
 * @param array $form
 *   A reference to the form array for which the event is being invoked.
 * @param array $form_state
 *   A reference to the form state array for which the event is being invoked.
 * @param string|null $form_id
 *   The form ID of the form for which the event is being invoked, or NULL. If
 *   NULL the form ID will be retrieved from the $form array.
 *
 * @see rules_forms_event_validate()
 * @see rules_forms_event_submit()
 * @see rules_forms_form_alter()
 */
function rules_forms_invoke_event($event_type, &$form, &$form_state, $form_id = NULL) {
  if (empty($form_id)) {
    $form_id = $form['form_id']['#value'];
  }

  // Wrap form data as an ArrayObject for passage to Rules.
  rules_invoke_event("rules_forms_{$form_id}_{$event_type}", new EntityMetadataArrayObject($form), new EntityMetadataArrayObject($form_state));
}

/**
 * Builds property info about the form structure if necessary.
 */
function rules_forms_after_build($form, &$form_state) {
  $form_id = $form['form_id']['#value'];
  $form_info = rules_forms_get_form_info($form_id);
  if ($form_info !== FALSE && !empty($form_info['rebuild'])) {
    $evaluator = new RulesFormsFormEvaluator();
    $property_info = $evaluator
      ->evaluate($form);

    // Allow modules to alter the property info directly.
    drupal_alter('rules_forms_form_property_info', $property_info, $form, $form_id);
    $form_info['properties'] = $property_info['properties'];
    $form_info['rebuild'] = FALSE;
    rules_forms_update_form_info($form_info);
    rules_forms_clear_cache();
    drupal_set_message(t('Form elements for %form have been built.', array(
      '%form' => $form_info['label'],
    )));
  }

  // @TODO Consider adding the element inspection tool.
  return $form;
}

/**
 * Activates events for a form.
 *
 * @param array $info
 *   The information to store.
 */
function rules_forms_activate_form(array $info) {
  $info += array(
    'properties' => array(
      'form' => array(),
      'form_state' => array(),
    ),
    'rebuild' => TRUE,
  );
  $fields = array(
    'form_id' => $info['form_id'],
    'label' => $info['label'],
    'properties' => serialize($info['properties']),
    'rebuild' => $info['rebuild'] == TRUE ? 1 : 0,
  );
  db_insert('rules_forms')
    ->fields($fields)
    ->execute();
  return SAVED_NEW;
}

/**
 * Updates information for a form.
 *
 * @param array $info
 *   The information to update.
 */
function rules_forms_update_form_info(array $info) {
  $fields = array(
    'form_id' => $info['form_id'],
    'label' => $info['label'],
    'properties' => serialize($info['properties']),
    'rebuild' => $info['rebuild'] == TRUE ? 1 : 0,
  );
  db_update('rules_forms')
    ->fields($fields)
    ->condition('form_id', $fields['form_id'])
    ->execute();
  return SAVED_UPDATED;
}

/**
 * Returns an array of information about active forms.
 *
 * @param string $form_id
 *   An optional form ID specifying the form about which to return information.
 */
function rules_forms_get_form_info($form_id = NULL) {
  if ($data = rules_forms_get_cache('rules_forms_info')) {
    $form_info = $data;
  }
  else {
    $form_info = array();
    if (!db_table_exists('rules_forms')) {
      return $form_info;
    }
    $results = db_select('rules_forms', 'rf')
      ->fields('rf')
      ->execute();
    foreach ($results as $info) {
      $info = (array) $info;
      $info['properties'] = unserialize($info['properties']);
      $info['rebuild'] = $info['rebuild'] == TRUE;
      $form_info[$info['form_id']] = $info;
    }
    rules_forms_set_cache('rules_forms_info', $form_info);
  }
  if (isset($form_id)) {
    return isset($form_info[$form_id]) ? $form_info[$form_id] : FALSE;
  }
  return $form_info;
}

/**
 * Deactivates events for a form.
 *
 * @param string $form_id
 *   The form ID.
 */
function rules_forms_deactivate_form($form_id) {
  db_delete('rules_forms')
    ->condition('form_id', $form_id)
    ->execute();
  return SAVED_DELETED;
}

/**
 * Returns element info defined in hook_rules_forms_element_info().
 */
function rules_forms_get_element_info($name = NULL) {
  $elements =& drupal_static(__FUNCTION__, array());
  if (empty($elements)) {
    if ($cache = rules_forms_get_cache('element_info')) {
      $elements = $cache;
    }
    else {
      foreach (module_invoke_all('rules_forms_element_info') as $key => $value) {
        $value += array(
          'element info' => array(),
        );
        $value['element info'] += array(
          'data type' => 'text',
        );
        $elements[$key] = $value;
      }
      drupal_alter('rules_forms_element_info', $elements);
      rules_forms_set_cache('element_info', $elements);
    }
  }
  if (isset($name) && isset($elements[$name])) {
    return $elements[$name];
  }
  return $elements;
}

Functions

Namesort descending Description
rules_forms_activate_form Activates events for a form.
rules_forms_after_build Builds property info about the form structure if necessary.
rules_forms_clear_cache Clears the Rules Forms and Rules caches.
rules_forms_create_structure Creates a data structure (array).
rules_forms_deactivate_form Deactivates events for a form.
rules_forms_event_build Form build handler. Stores form values and invokes the event.
rules_forms_event_submit Submit handler to invoke "form submitted" events.
rules_forms_event_validate Validation handler to invoke "form validate" events.
rules_forms_flush_caches Implements hook_flush_caches().
rules_forms_form_alter Implements hook_form_alter().
rules_forms_get_cache Returns cached data.
rules_forms_get_element_info Returns element info defined in hook_rules_forms_element_info().
rules_forms_get_form_info Returns an array of information about active forms.
rules_forms_help Implements hook_help().
rules_forms_hook_info Implements hook_hook_info().
rules_forms_invoke_event Invoke rules event of a certain type.
rules_forms_menu Implements hook_menu().
rules_forms_permission Implements hook_permission().
rules_forms_set_cache Caches data.
rules_forms_update_form_info Updates information for a form.

Constants

Namesort descending Description
RULES_FORMS_ADMIN_PATH @file Rules Forms Support provides events, conditions, and actions for site forms.