You are here

function patterns_implement_action in Patterns 7.2

Same name and namespace in other branches
  1. 6.2 patterns.module \patterns_implement_action()
  2. 6 patterns.module \patterns_implement_action()
  3. 7 includes/core/common.inc \patterns_implement_action()

Setup and run an action.

Parameters

$action:

$identifiers:

$place: s_map

Return value

@TODO Doc.

2 calls to patterns_implement_action()
patterns_batch_action in includes/core/batch.inc
Executes a batch action.
patterns_php_action in includes/core/php.inc
Execute a single pattern action.

File

includes/core/common.inc, line 73
The common functions used by the Batch and PHP running modes.

Code

function patterns_implement_action($action, $data, &$identifiers, $place = 0, $actions_map = NULL) {
  patterns_set_error_handler();
  $status = PATTERNS_SUCCESS;
  $msg = '';

  // Refresh the list of forms based on the data we have.
  $tagmodules = patterns_tagmodules_get_index($data);
  $tag_info = patterns_tagmodules_filter($tagmodules, $data['tag']);
  $tag_description = isset($tag_info['description']) ? $tag_info['description'] : 'no description';
  $form_ids = $tag_info[$action];

  // Gather info about the action
  $action_location = patterns_locate_action($place, $actions_map);
  $index = $action_location['key'] + 1;
  $pattern_title = $action_location['title'];
  $pattern_file = $action_location['file'];

  // See which forms to execute sequentially. This is similar to what used to be called 'form_ids'.
  $results = patterns_invoke('callbacks', $action, $data);
  if (!patterns_error_check_results($results)) {
    return $results;
  }

  // If no special callback was returned, we use the functions
  // specified in the hook_patterns for the action
  if (!isset($results['result']) || empty($results['result'])) {
    $funcs = $form_ids;
  }
  else {
    $funcs = $results['result'];
  }

  // Auto include FILES
  if (!empty($tag_info[PATTERNS_FILES])) {
    foreach ($tag_info[PATTERNS_FILES] as $file) {
      require_once $file;
    }
  }

  // Build the action
  foreach ($funcs as $func) {
    $form_id = $func;
    $clone = $data;

    // TODO: does this prevent subsequent form_ids' communication?
    $results['action_descriptions'][$place][] = $tag_info['descr'];

    // If tokens are enabled, apply tokens to the action values
    // before processing.
    if (module_exists('token')) {
      _patterns_recurse_tokens($clone, $identifiers);
    }

    /////////////////////////////////////////////////////

    // BUILD: Get the form data for the action. This can return either
    // just the form values, or the full form_state object.

    /////////////////////////////////////////////////////
    $results = patterns_invoke('build', $action, $clone, $form_id);
    if (!patterns_error_check_results($results)) {
      return $results;
    }

    // If no special callback was returned, we use the data as it is
    if (!isset($results['result']) || empty($results['result'])) {
      $form_obj = $clone;
    }
    else {
      $form_obj = $results['result'];
    }

    // We check for the 'storage' and 'submitted' values in the object to see
    // if it is a form_state instead of form_values. There could be a better way
    // to do this.
    if (array_key_exists('submitted', (array) $form_obj) && array_key_exists('storage', (array) $form_obj)) {
      $action_state = $form_obj;
      $need_buildinfo = TRUE;
    }
    else {
      if (!isset($tag_info['files'])) {
        $files = array();
      }
      else {
        $files = $tag_info['files'];
      }
      $action_state = array(
        'storage' => NULL,
        'submitted' => FALSE,
        'build_info' => array(
          'files' => $files,
        ),
        'values' => $form_obj,
      );
      $need_buildinfo = TRUE;
    }

    ////////////////////////////////////////////////////

    // Get any extra parameters required for the action

    ////////////////////////////////////////////////////
    $results = patterns_invoke('params', $action, $clone, $form_id, $action_state);
    if (!patterns_error_check_results($results)) {
      return $results;
    }

    // A single, simple value can be returned as a parameter, which is then
    // put into an array here.
    if (!isset($results['result'])) {
      $results['result'] = NULL;
    }
    if (!is_array($results['result'])) {
      $params = array(
        $results['result'],
      );
    }
    else {
      $params = $results['result'];
    }
    if ($need_buildinfo) {
      $action_state['build_info']['args'] = $params;
    }

    ///////////////////

    // Execute action: pass action_state and params to a form

    ///////////////////
    patterns_execute_action($form_id, $action_state, $params);
    if ($errors = form_get_errors()) {
      drupal_set_message(print_r($errors, true));
      $errors_tokens = array(
        '%num' => $index,
        '%action' => $tag_description,
        '%title' => $pattern_title,
        '%errors' => str_replace('][', '->', implode(', ', array_keys($errors))),
      );
      $msg = t('Above error(s) occurred while executing action #%num (%action) in %title pattern. Error location(s) are: %errors', $errors_tokens);
      return patterns_results(PATTERN_ERR, $msg);
    }

    ////////////////////

    // CLEAN UP: Let a component cleanup after each action

    ////////////////////
    $results = patterns_invoke('cleanup', $action, $clone, $form_id, $action_state);

    // Do not return here, just print on screen
    patterns_error_check_results($results);
  }

  // End: Form_id execution
  // Clear the cache in case it causes problems
  cache_clear_all();
  patterns_restore_error_handler();
  return patterns_results();
}