You are here

public static function WorkflowTransitionElement::copyFormValuesToTransition in Workflow 8

Implements ContentEntityForm::copyFormValuesToEntity().

This is called from:

  • WorkflowTransitionForm::copyFormValuesToEntity(),
  • WorkflowDefaultWidget.

N.B. in contrary to ContentEntityForm::copyFormValuesToEntity(),

  • parameter 1 is returned as result, to be able to create a new Transition object.
  • parameter 3 is not $form_state (from Form), but an $item array (from Widget).

Parameters

\Drupal\Core\Entity\EntityInterface $transition:

array $form:

\Drupal\Core\Form\FormStateInterface $form_state:

array $item:

Return value

\Drupal\workflow\Entity\WorkflowTransitionInterface A new Transition object.

2 calls to WorkflowTransitionElement::copyFormValuesToTransition()
WorkflowDefaultWidget::massageFormValues in src/Plugin/Field/FieldWidget/WorkflowDefaultWidget.php
Implements workflow_transition() -> WorkflowDefaultWidget::submit().
WorkflowTransitionForm::copyFormValuesToEntity in src/Form/WorkflowTransitionForm.php
Copies top-level form values to entity properties

File

src/Element/WorkflowTransitionElement.php, line 413

Class

WorkflowTransitionElement
Provides a form element for the WorkflowTransitionForm and ~Widget.

Namespace

Drupal\workflow\Element

Code

public static function copyFormValuesToTransition(EntityInterface $transition, array $form, FormStateInterface $form_state, array $item) {

  /** @var \Drupal\workflow\Entity\WorkflowTransitionInterface $transition */

  // @todo #2287057: verify if submit() really is only used for UI. If not, $user must be passed.

  /** @var \Drupal\user\UserInterface $user */
  $user = workflow_current_user();

  /*
   * Derived input
   */

  // Make sure we have subset ['workflow_scheduled_date_time'].
  if (!isset($item['to_sid'])) {
    $entity_id = $transition
      ->getTargetEntityId();
    \Drupal::messenger()
      ->addError(t('Error: content @id has no workflow attached. The data is not saved.', [
      '@id' => $entity_id,
    ]));

    // The new state is still the previous state.
    return $transition;
  }

  // In WorkflowTransitionForm, we receive the complete $form_state.
  // Remember, the workflow_scheduled element is not set on 'add' page.
  $scheduled = !empty($item['workflow_scheduling']['scheduled']);
  $schedule_values = $scheduled ? $item['workflow_scheduling']['date_time'] : [];

  // Get user input from element.
  $to_sid = $item['to_sid'];
  $comment = $item['comment'];
  $force = FALSE;

  // @todo D8: add the VBO use case.

  /*
      // Determine if the transition is forced.
      // This can be set by a 'workflow_vbo action' in an additional form element.
      $force = isset($form_state['input']['workflow_force'])
      ? $form_state['input']['workflow_force'] : FALSE;
      if (!$entity) {
   // E.g., on VBO form.
      }
  */

  // @todo D8: add below exception.
  // Extract the data from $items, depending on the type of widget.
  // @todo D8: use MassageFormValues($item, $form, $form_state).

  /*
      $old_sid = workflow_node_previous_state($entity, $entity_type, $field_name);
      if (!$old_sid) {
   // At this moment, $old_sid should have a value. If the content does not
   // have a state yet, old_sid contains '(creation)' state. But if the
   // content is not associated to a workflow, old_sid is now 0. This may
   // happen in workflow_vbo, if you assign a state to non-relevant nodes.
   $entity_id = entity_id($entity_type, $entity);
   \Drupal::messenger()->addError(t('Error: content @id has no workflow
     attached. The data is not saved.', ['@id' => $entity_id]));
   // The new state is still the previous state.
   $new_sid = $old_sid;
   return $new_sid;
      }
  */
  $timestamp = \Drupal::time()
    ->getRequestTime();
  if ($scheduled) {

    // Fetch the (scheduled) timestamp to change the state.
    // Override $timestamp.
    $scheduled_date_time = implode(' ', [
      $schedule_values['workflow_scheduled_date'],
      $schedule_values['workflow_scheduled_hour'],
    ]);
    $timezone = $schedule_values['workflow_scheduled_timezone'];
    $old_timezone = date_default_timezone_get();
    date_default_timezone_set($timezone);
    $timestamp = strtotime($scheduled_date_time);
    date_default_timezone_set($old_timezone);
    if (!$timestamp) {

      // Time should have been validated in form/widget.
      $timestamp = \Drupal::time()
        ->getRequestTime();
    }
  }

  /*
   * Process.
   */

  /*
   * Create a new ScheduledTransition.
   */
  if ($scheduled) {
    $transition_entity = $transition
      ->getTargetEntity();
    $field_name = $transition
      ->getFieldName();
    $from_sid = $transition
      ->getFromSid();

    /** @var \Drupal\workflow\Entity\WorkflowTransitionInterface $transition */
    $transition = WorkflowScheduledTransition::create([
      $from_sid,
      'field_name' => $field_name,
    ]);
    $transition
      ->setTargetEntity($transition_entity);
    $transition
      ->setValues($to_sid, $user
      ->id(), $timestamp, $comment);
  }
  if (!$transition
    ->isExecuted()) {

    // Set new values.
    // When editing an existing Transition, only comments may change.
    $transition
      ->setValues($to_sid, $user
      ->id(), $timestamp, $comment);
    $transition
      ->schedule($scheduled);
    $transition
      ->force($force);
  }
  $transition
    ->setComment($comment);

  // Determine and add the attached fields.
  // Caveat: This works automatically on a Workflow Form,
  // but only with a hack on a widget.
  // @todo Attached fields are not supported in ScheduledTransitions.
  $fields = WorkflowManager::getAttachedFields('workflow_transition', $transition
    ->bundle());

  /** @var \Drupal\Core\Field\Entity\BaseFieldOverride $field */
  foreach ($fields as $field_name => $field) {
    $user_input = isset($form_state
      ->getUserInput()[$field_name]) ? $form_state
      ->getUserInput()[$field_name] : [];
    if (isset($item[$field_name])) {

      // On Workflow Form (e.g., history tab, block).
      // @todo In latest tests, this line seems not necessary.
      $transition->{$field_name} = $item[$field_name];
    }
    elseif ($user_input) {

      // On Workflow Widget (e.g., on node, comment).
      // @todo Some field types are not supported here.
      $transition->{$field_name} = $user_input;
    }

    // #2899025 As a workaround for field types not supported,
    // let other modules modify the copied values.
    $context = [
      'field' => $field,
      'field_name' => $field_name,
      'user_input' => $user_input,
      'item' => $item,
    ];
    \Drupal::moduleHandler()
      ->alter('copy_form_values_to_transition_field', $transition, $context);
  }
  return $transition;
}