You are here

function patterns_execute_pattern in Patterns 5

Same name and namespace in other branches
  1. 6.2 patterns.module \patterns_execute_pattern()
  2. 6 patterns.module \patterns_execute_pattern()
2 calls to patterns_execute_pattern()
patterns_disable_pattern_submit in ./patterns.module
patterns_enable_pattern_submit in ./patterns.module

File

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

Code

function patterns_execute_pattern($pattern, $reverse = false, $interact = false, $jump = null) {
  patterns_load();
  set_time_limit(0);
  if (!is_object($pattern)) {
    $pattern = patterns_get_pattern($pattern);
    if (!$pattern) {
      return false;
    }
  }
  $errors = $action_list = $identifiers = array();
  $error = true;

  // Pattern info
  $status = $pattern->status;
  $title = $pattern->title;
  $pid = $pattern->pid;

  // From here on out just need the actual pattern data
  $pattern = $pattern->pattern;

  // Split the pattern up into modules and actions. Submit modules as its
  // own pattern programattically.
  $modules = $actions = array();
  for ($i = 0; $tag = $pattern[$i]; $i++) {
    if ($tag['tag'] == 'modules') {
      $modules = $tag;
    }
    else {
      if ($tag['tag'] == 'actions') {
        $actions = $tag;
        unset($actions['tag']);
      }
    }
  }

  // If there are no actions or modules, most likely the pattern
  // was not created correctly.
  if (empty($actions) && empty($modules)) {
    drupal_set_message(t('Could not recognize pattern %title, aborting.', array(
      '%title' => $title,
    )), 'error');
    return true;
  }
  if ($modules && (!$interact || $interact && !$jump)) {

    // Make the modules look like a normal pattern so they can be executed
    // on their own.
    $obj = new stdClass();
    $obj->title = t('Enable/disable %title pattern modules', array(
      '%title' => $title,
    ));
    $obj->status = $status;
    $obj->pattern = array(
      array(
        'tag' => 'actions',
        $modules,
      ),
    );
    $modules = $obj;

    // Modules need to be enabled first so the rest of the pattern
    // can proceed smoothly.
    if (!$reverse) {
      $error = patterns_execute_pattern($modules, $reverse, $interact);
      module_rebuild_cache();
    }
  }

  // Keep a list of what modules handle what tags
  $tag_modules = patterns_invoke($empty, 'tag modules');

  // If an interactive pattern needs resuming, remove the
  // already executed actions
  if ($interact && $jump > 0) {
    array_splice($actions, 0, $jump);
  }

  // Prepare actions for validation/processing
  foreach ($actions as $key => $data) {
    patterns_invoke($actions[$key], 'prepare');
  }

  // Reverse a pattern for disabling
  if ($reverse && $status) {
    $actions = array_reverse($actions);
    foreach ($actions as $key => $data) {
      $continue = patterns_invoke($data, 'reverse');
      if ($continue === false) {
        drupal_set_message(t('[Error] Disabling of this pattern is not supported at this time.'));
        return false;
      }
      $actions[$key] = $data;
    }
  }

  // Pre validate tags with their appropriate components
  foreach ($actions as $key => $data) {
    if (!array_key_exists($data['tag'], $tag_modules)) {
      $errors[$data['tag']][] = t('Invalid Pattern: <%tag> is not a valid tag', array(
        '%tag' => $data['tag'],
      ));
    }
    else {
      $error = patterns_invoke($data, 'pre-validate');
      if ($error) {
        $errors[$data['tag']][] = t('Invalid Pattern: !msg', array(
          '!msg' => $error,
        ));
      }
    }
  }
  if (count($errors)) {
    foreach ($errors as $error) {
      drupal_set_message(implode('<br>', $error), 'error');
    }
    return;
  }

  // Build and execute a list of actions
  foreach ($actions as $key => $data) {

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

    // If prepare removed the data, dont continue with this action
    if (!$data || !$return) {
      continue;
    }
    if (is_string($return)) {
      $form_ids = array(
        $return,
      );
    }
    else {
      if ($return) {
        $form_ids = $return;
      }
    }

    // Build the action
    foreach ($form_ids as $form_id) {
      $clone = $data;
      $error = patterns_invoke($clone, 'validate', $form_id);
      if ($error) {
        if (is_array($error)) {
          foreach ($error as $msg) {
            drupal_set_message($msg, 'error');
          }
          $errors[$clone['tag']] = t('Broken Pattern: %msg', array(
            '%msg' => implode('<br>', $error),
          ));
        }
        else {
          drupal_set_message($error, 'error');
          $errors[$clone['tag']] = t('Broken Pattern: %msg', array(
            '%msg' => $error,
          ));
        }
        return;
      }

      // 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);
      }

      // Get the form data for the action
      $values = patterns_invoke($clone, 'build', $form_id);

      // 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($values)) {
        drupal_set_message($values);
      }
      else {

        // Get any extra parameters required for the action
        $params = patterns_invoke($clone, 'params', $form_id, $values);
        if (isset($params) && !is_array($params)) {
          $params = array(
            $params,
          );
        }

        // Execute action
        patterns_execute_action($form_id, $values, $params);
        if (form_get_errors()) {
          $descriptions = patterns_invoke($clone, 'actions');
          drupal_set_message(t('An error occured running action #%num (%action)', array(
            '%num' => $key + 1,
            '%action' => $descriptions[$form_id],
          )), 'error');
          $error = true;
          break;
        }
      }
      patterns_invoke($clone, 'cleanup', $form_id);

      // Clear the cache in case it causes problems
      cache_clear_all();
    }
    if ($error) {
      break;
    }

    // Get any primary identifiers from the action for further actions to take advantage of
    $id = null;
    $id = patterns_invoke($clone, 'identifier', $form_id);
    if (isset($id)) {
      $identifiers[$key + 1] = $id;
    }
  }
  if (empty($errors)) {
    if ($reverse) {
      if ($modules) {

        // Modules need to be disabled last so the rest of the pattern
        // can reverse itself properly
        $error = patterns_execute_pattern($modules, $reverse, $interact);
      }

      // Mark pattern as disabled
      if ($pid) {
        db_query('UPDATE {patterns} SET status = 0 WHERE pid = %d', $pid);
      }
      drupal_set_message(t('Pattern reversed successfully.'));
    }
    else {

      // Mark pattern as enabled
      if ($pid) {
        db_query('UPDATE {patterns} SET status = 1, enabled = "%s" WHERE pid = %d', time(), $pid);
      }
      drupal_set_message(t('Pattern ran successfully.'));
    }
  }
  return !$error;
}