You are here

function patterns_implement_action in Patterns 6

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

Setup and run an action

1 call to patterns_implement_action()
patterns_batch_actions in ./patterns.module
Execute a batch action

File

./patterns.module, line 1574
Enables extremely simple adding/removing features to your site with minimal to no configuration

Code

function patterns_implement_action($action, &$identifiers, $place = 0, $actions_map = NULL) {
  patterns_set_error_handler();
  $result = array(
    'success' => TRUE,
  );

  // Prepare actions for processing, ensure smooth pattern executions, and return form ids for execution
  $return = patterns_invoke($action, 'form_id');

  // If prepare removed the data, dont continue with this action
  if (!$action || !$return) {
    return $result;
  }
  if (is_string($return)) {
    $form_ids = array(
      $return,
    );
  }
  else {
    if ($return) {
      $form_ids = $return;
    }
  }
  $action_descriptions = patterns_invoke($action, 'actions');
  $action_location = patterns_locate_action($place, $actions_map);
  $index = $action_location['key'] + 1;
  $pattern_title = $action_location['title'];
  $pattern_file = $action_location['file'];

  // Build the action
  foreach ($form_ids as $form_id) {
    $clone = $action;
    $action_description = isset($action_descriptions[$form_id]) ? $action_descriptions[$form_id] : t('System: Execute form');
    $result['action_descriptions'][$place][] = $action_description;

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

      //array_walk($clone, '_patterns_replace_tokens', $identifiers);
    }
    $error = patterns_invoke($clone, 'validate', $form_id);
    if ($message = patterns_error_get_last('validate', $index, $action_description, $pattern_title, $pattern_file)) {
      $result['error_message'] = $message;
      $result['success'] = FALSE;
      return $result;
    }
    if ($error) {
      $message = t('An error occured while validating action #%num (%action) in %title pattern', array(
        '%num' => $index,
        '%action' => $action_description,
        '%title' => $pattern_title,
      ));
      $result['error_message'] = $message . '<br>' . $error;
      $result['success'] = FALSE;
      return $result;
    }

    // Get the form data for the action. This can either just be the form values,
    // or it can be the full form_state object
    $form_obj = patterns_invoke($clone, 'build', $form_id);
    if ($message = patterns_error_get_last('build', $index, $action_description, $pattern_title, $pattern_file)) {
      $result['error_message'] = $message;
      $result['success'] = FALSE;
      return $result;
    }

    // Dont execute the action if a string was returned, indicating the pattern component
    // most likely handled the action on its own and this is the message to display.
    if (is_string($form_obj)) {
      drupal_set_message($form_obj);
    }
    else {

      // 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;
      }
      else {
        $action_state = array(
          'storage' => null,
          'submitted' => false,
          'values' => $form_obj,
        );
      }

      // Get any extra parameters required for the action
      $params = patterns_invoke($clone, 'params', $form_id, $action_state);
      if ($message = patterns_error_get_last('params', $index, $action_description, $pattern_title, $pattern_file)) {
        $result['error_message'] = $message;
        $result['success'] = FALSE;
        return $result;
      }

      // A single, simple value can be returned as a parameter, which is then
      // put into an array here.
      if (isset($params) && !is_array($params)) {
        $params = array(
          $params,
        );
      }

      // Execute action
      patterns_execute_action($form_id, $action_state, $params);
      if ($message = patterns_error_get_last('execute', $index, $action_description, $pattern_title, $pattern_file)) {
        $result['error_message'] = $message;
        $result['success'] = FALSE;
        return $result;
      }
      if ($errors = form_get_errors()) {
        $result['error_message'] = t('Above error(s) occured while executing action #%num (%action) in %title pattern. Error location(s) are: %errors', array(
          '%num' => $index,
          '%action' => $action_description,
          '%title' => $pattern_title,
          '%errors' => str_replace('][', '->', implode(', ', array_keys($errors))),
        ));
        $result['success'] = FALSE;
        return $result;
      }

      // Let a component cleanup after each action
      patterns_invoke($clone, 'cleanup', $form_id, $action_state);
      if ($message = patterns_error_get_last('cleanup', $index, $action_description, $pattern_title, $pattern_file)) {
        $result['error_message'] = $message;
        $result['success'] = FALSE;
        return $result;
      }
    }

    // Clear the cache in case it causes problems
    cache_clear_all();

    // Rebuild the menu
    // TODO Should this go at the end only when a pattern successfully runs?
    variable_set('menu_rebuild_needed', true);
  }

  // Get any primary identifiers from the action for further actions to take advantage of
  $id = null;
  $id = patterns_invoke($clone, 'identifier', $form_id, $action_state);
  if (isset($id)) {
    $index = isset($clone['action_label']) ? $clone['action_label'] : $place + 1;
    $identifiers[$index] = $id;
  }
  patterns_restore_error_handler();
  return $result;
}