You are here

public function WorkflowTransition::execute in Workflow 7

Same name and namespace in other branches
  1. 7.2 includes/Entity/WorkflowTransition.php \WorkflowTransition::execute()

Execute a transition (change state of a node). @deprecated: workflow_execute_transition() --> WorkflowTransition::execute().

Parameters

$node:

$sid: Target state ID.

$comment: A comment for the node's workflow history.

$force: If set to TRUE, workflow permissions will be ignored.

array $field: A field_info data structure, used when changing a Workflow Field

$old_sid: The current/old State ID. Passed if known by caller. @todo: D8: make $old_sid parameter required.

Return value

int ID of new state.

File

includes/Entity/WorkflowTransition.php, line 108
Contains workflow\includes\Entity\WorkflowTransition.

Class

WorkflowTransition
Implements an actual Transition.

Code

public function execute($force = FALSE) {
  global $user;
  $old_sid = $this->old_sid;
  $new_sid = $this->new_sid;
  $entity_type = $this->entity_type;
  $entity_id = $this->entity_id;
  $entity = $this
    ->getEntity();

  // Entity may not be loaded, yet.
  $field_name = $this->field_name;
  if (!$force) {

    // Make sure this transition is allowed.
    $result = module_invoke_all('workflow', 'transition permitted', $new_sid, $old_sid, $entity, $force, $entity_type, $field_name);

    // Did anybody veto this choice?
    if (in_array(FALSE, $result)) {

      // If vetoed, quit.
      return $old_sid;
    }
  }

  // Let other modules modify the comment.

  //@todo D8: remove a but last items from $context.
  $context = array(
    'node' => $entity,
    'sid' => $new_sid,
    'old_sid' => $old_sid,
    'uid' => $this->uid,
    'transition' => $this,
  );
  drupal_alter('workflow_comment', $this->comment, $context);
  if ($old_sid == $new_sid) {

    // Stop if not going to a different state.
    // Write comment into history though.
    if ($this->comment) {
      $this->stamp = REQUEST_TIME;

      // @todo D8: remove; this is only for Node API.
      $entity->workflow_stamp = REQUEST_TIME;
      workflow_update_workflow_node_stamp($entity_id, $this->stamp);

      //@todo: only for Node API
      $result = module_invoke_all('workflow', 'transition pre', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
      $data = array(
        'nid' => $entity_id,
        'sid' => $new_sid,
        'old_sid' => $old_sid,
        'uid' => $this->uid,
        'stamp' => $this->stamp,
        'comment' => $this->comment,
      );
      workflow_insert_workflow_node_history($data);
      unset($entity->workflow_comment);

      // @todo D8: remove; this line is only for Node API.
      $result = module_invoke_all('workflow', 'transition post', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);
    }

    // Clear any references in the scheduled listing.
    foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
      $scheduled_transition
        ->delete();
    }
    return $old_sid;
  }
  $transition = workflow_get_workflow_transitions_by_sid_target_sid($old_sid, $new_sid);
  if (!$transition && !$force) {
    watchdog('workflow', 'Attempt to go to nonexistent transition (from %old to %new)', array(
      '%old' => $old_sid,
      '%new' => $new_sid,
      WATCHDOG_ERROR,
    ));
    return $old_sid;
  }

  // Make sure this transition is valid and allowed for the current user.
  // Check allow-ability of state change if user is not superuser (might be cron).
  if ($user->uid != 1 && !$force) {
    if (!workflow_transition_allowed($transition->tid, array_merge(array_keys($user->roles), array(
      'author',
    )))) {
      watchdog('workflow', 'User %user not allowed to go from state %old to %new', array(
        '%user' => $user->name,
        '%old' => $old_sid,
        '%new' => $new_sid,
        WATCHDOG_NOTICE,
      ));
      return $old_sid;
    }
  }

  // Invoke a callback indicating a transition is about to occur.
  // Modules may veto the transition by returning FALSE.
  $result = module_invoke_all('workflow', 'transition pre', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);

  // Stop if a module says so.
  if (in_array(FALSE, $result)) {
    watchdog('workflow', 'Transition vetoed by module.');
    return $old_sid;
  }

  // If the node does not have an existing $node->workflow property, save the $old_sid there so it can be logged.
  // This is only valid for Node API.
  // @todo: why is this set here? It is set again 16 lines down.
  if (!$field_name && !isset($node->workflow)) {
    $node->workflow = $old_sid;
  }

  // Change the state.
  $data = array(
    'nid' => $entity_id,
    'sid' => $new_sid,
    'uid' => isset($node->workflow_uid) ? $node->workflow_uid : $user->uid,
    'stamp' => REQUEST_TIME,
  );

  // Workflow_update_workflow_node places a history comment as well.
  workflow_update_workflow_node($data, $old_sid, $this->comment);
  if (!$field_name) {

    /// Only for Node API.
    $node->workflow = $new_sid;
  }

  // Register state change with watchdog.
  if ($state = WorkflowState::load($new_sid)) {
    $workflow = $state
      ->getWorkflow();
    if ($workflow->options['watchdog_log']) {
      $message = $this
        ->isScheduled() ? 'Scheduled state change of @type %node_title to %state_name executed' : 'State of @type %node_title set to %state_name';
      $args = array(
        '@type' => ($type = node_type_get_name($entity->type)) ? $type : $entity->type,
        '%node_title' => isset($entity->title) ? $entity->title : $entity->type,
        //@todo: enable entity API.
        '%state_name' => $state
          ->label(),
      );
      $uri = entity_uri($entity_type, $entity);
      watchdog('workflow', $message, $args, WATCHDOG_NOTICE, l('view', $uri['path']));
    }
  }

  // Notify modules that transition has occurred. Action triggers should take place in response to this callback, not the previous one.
  module_invoke_all('workflow', 'transition post', $old_sid, $new_sid, $entity, $force, $entity_type, $field_name);

  // Clear any references in the scheduled listing.
  foreach (WorkflowScheduledTransition::load($entity_type, $entity_id, $field_name) as $scheduled_transition) {
    $scheduled_transition
      ->delete();
  }
  return $new_sid;
}