flow-1.0.0-beta8/modules/flow_ui/src/Form/TaskForm.php

modules/flow_ui/src/Form/TaskForm.php
<?php

namespace Drupal\flow_ui\Form;

use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\flow\Entity\Flow;
use Drupal\flow\Entity\FlowInterface;
use Drupal\flow\FlowCompatibility;
use Drupal\flow\FlowTaskMode;
use Drupal\flow\Plugin\FlowSubjectInterface;
use Drupal\flow\Plugin\FlowTaskInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form for configuring a Flow task plugin.
 */
class TaskForm implements FormInterface, ContainerInjectionInterface {

  use DependencySerializationTrait;
  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected MessengerInterface $messenger;

  /**
   * The Flow config entity.
   *
   * @var \Drupal\flow\Entity\FlowInterface|null
   */
  protected ?FlowInterface $flow;

  /**
   * The Flow task plugin.
   *
   * @var \Drupal\flow\Plugin\FlowTaskInterface|null
   */
  protected ?FlowTaskInterface $task;

  /**
   * The Flow subject plugin.
   *
   * @var \Drupal\flow\Plugin\FlowSubjectInterface|null
   */
  protected ?FlowSubjectInterface $subject;

  /**
   * The position of the Flow task within the tasks list of the Flow config.
   *
   * @var int|null
   */
  protected ?int $taskIndex;

  /**
   * The target entity type.
   *
   * @var \Drupal\Core\Entity\EntityTypeInterface
   */
  protected EntityTypeInterface $targetEntityType;

  /**
   * This flag indicates whether a new task has been saved.
   *
   * @var bool
   */
  protected bool $savedNewTask = FALSE;

  /**
   * The TaskForm constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   * @param \Drupal\flow\Entity\FlowInterface|null $flow
   *   The Flow config entity.
   * @param \Drupal\flow\Plugin\FlowTaskInterface|null $task
   *   The Flow task plugin.
   * @param \Drupal\flow\Plugin\FlowSubjectInterface|null $subject
   *   The Flow subject plugin.
   * @param int|null $task_index
   *   The position of the Flow task within the tasks list of the Flow config.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, MessengerInterface $messenger, ?FlowInterface $flow = NULL, ?FlowTaskInterface $task = NULL, ?FlowSubjectInterface $subject = NULL, ?int $task_index = NULL) {
    $this->entityTypeManager = $entity_type_manager;
    $this->messenger = $messenger;
    $this->flow = $flow;
    $this->task = $task;
    $this->subject = $subject;
    $this->taskIndex = $task_index;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, ?FlowInterface $flow = NULL, ?FlowTaskInterface $task = NULL, ?FlowSubjectInterface $subject = NULL, ?int $task_index = NULL) {
    $instance = new static($container->get('entity_type.manager'), $container->get('messenger'), $flow, $task, $subject, $task_index);
    $instance->setStringTranslation($container->get('string_translation'));
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'flow_task_plugin';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, ?FlowInterface $flow = NULL, ?FlowTaskInterface $task = NULL, ?FlowSubjectInterface $subject = NULL, ?int $task_index = NULL) {
    $form['#tree'] = TRUE;
    $form['#process'][] = '::processForm';
    $form['#after_build'][] = '::afterBuild';
    $this->initProperties($form, $form_state, $flow, $task, $subject, $task_index);
    $task = $this->task;
    $subject = $this->subject;
    $task_definition = $task->getPluginDefinition();
    $task_config = $task->getConfiguration();

    $weight = 0;
    $task_is_new = !($this->taskIndex < $this->flow->getTasks()->count());

    $weight += 10;
    $subject_definition = $this->subject->getPluginDefinition();
    $form['subject'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('@type: @name', [
        '@type' => $this->t('Subject'),
        '@name' => $subject_definition['label'],
      ]),
      '#weight' => $weight++,
    ];
    if ($subject instanceof PluginFormInterface) {
      $form['subject']['settings'] = [];
      $subject_form_state = SubformState::createForSubform($form['subject']['settings'], $form, $form_state);
      $form['subject']['settings'] = $subject->buildConfigurationForm($form['subject']['settings'], $subject_form_state);
    }
    else {
      $form['subject']['no_settings'] = [
        '#type' => 'markup',
        '#markup' => $this->t('This subject does not provide any settings.'),
      ];
    }

    $form['task'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('@type: @name', [
        '@type' => $this->t('Task'),
        '@name' => $task_definition['label'],
      ]),
      '#weight' => $weight++,
    ];
    if ($task instanceof PluginFormInterface) {
      $form['task']['settings'] = [];
      $task_form_state = SubformState::createForSubform($form['task']['settings'], $form, $form_state);
      $form['task']['settings'] = $task->buildConfigurationForm($form['task']['settings'], $task_form_state);
    }
    else {
      $form['task']['no_settings'] = [
        '#type' => 'markup',
        '#markup' => $this->t('This task does not provide any settings.'),
      ];
    }

    $weight += 10;
    $form['execution'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Task execution'),
      '#weight' => $weight++,
    ];
    $mode = $this->flow->isCustom() ? $flow->get('custom')['baseMode'] : $flow->getTaskMode();
    $execution_options = [
      'now' => $this->t('Immediately on @mode', ['@mode' => $mode]),
      'after' => $this->t('Immediately after @mode', ['@mode' => $mode]),
      'queue' => $this->t('Enqueue for running in the background'),
    ];
    $form['execution']['start'] = [
      '#type' => 'select',
      '#title' => $this->t('Start method'),
      '#title_display' => 'invisible',
      '#description' => $this->t('Different values of information may be available during and after the @mode operation. For example, when a new @type item is being created, the @type ID is only available after it got saved.', [
        '@type' => $this->entityTypeManager->getDefinition($this->flow->getTargetEntityTypeId())->getLabel(),
        '@mode' => $mode,
      ]),
      '#options' => $execution_options,
      '#default_value' => $task_config['execution']['start'] ?? 'now',
      '#required' => TRUE,
      '#weight' => 10,
    ];

    $weight += 100;
    $form['actions']['#weight'] = $weight++;
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save'),
      '#submit' => ['::submitForm', '::save', '::redirectAfterSave'],
      '#weight' => 10,
    ];
    if (!$task_is_new && isset($task_config['active']) && !$task_config['active']) {
      $form['actions']['delete'] = [
        '#type' => 'submit',
        '#value' => $this->t('Delete'),
        '#access' => $this->flow->access('delete'),
        '#submit' => ['::delete'],
        '#attributes' => [
          'class' => ['button', 'button--danger'],
        ],
        '#button_type' => 'danger',
        '#weight' => 20,
      ];
    }

    $form['config'] = ['#tree' => TRUE, '#weight' => $weight++];
    $form['config']['entity_type'] = [
      '#type' => 'hidden',
      '#value' => $this->flow->getTargetEntityTypeId(),
    ];
    $form['config']['bundle'] = [
      '#type' => 'hidden',
      '#value' => $this->flow->getTargetBundle(),
    ];
    $form['config']['task_mode'] = [
      '#type' => 'hidden',
      '#value' => $this->flow->getTaskMode(),
    ];
    $form['config']['task_plugin_id'] = [
      '#type' => 'hidden',
      '#value' => $this->task->getPluginId(),
    ];
    $form['config']['subject_plugin_id'] = [
      '#type' => 'hidden',
      '#value' => $this->subject->getPluginId(),
    ];
    $form['config']['task_index'] = [
      '#type' => 'hidden',
      '#value' => $this->taskIndex,
    ];

    return $form;
  }

  /**
   * Process callback.
   */
  public function processForm($element, FormStateInterface $form_state, $form) {
    $this->flow = $form_state->get('flow');
    $this->task = $form_state->get('task');
    $this->subject = $form_state->get('subject');
    $this->taskIndex = $form_state->get('task_index');
    return $element;
  }

  /**
   * After build callback.
   */
  public function afterBuild(array $form, FormStateInterface $form_state) {
    $subject = $this->subject;
    $task = $this->task;

    // Prevent Inline Entity Form from saving nested data.
    // @todo Find a better way to prevent submit handlers from saving data.
    if ($triggering_element = &$form_state->getTriggeringElement()) {
      if (isset($triggering_element['#ief_submit_trigger']) && !empty($triggering_element['#submit']) && is_array($triggering_element['#submit'])) {
        foreach ($triggering_element['#submit'] as $i => $submit_handler) {
          if (is_array($submit_handler) && (reset($submit_handler) === 'Drupal\\inline_entity_form\\ElementSubmit') && end($submit_handler) === 'trigger') {
            unset($triggering_element['#submit'][$i]);
          }
        }
      }
    }

    if ($form_state->hasValue(['task', 'settings']) && $task instanceof PluginFormInterface) {
      $values = $form_state->getValue(['task', 'settings']);
      array_walk_recursive($values, function (&$value) {
        if ($value === '_none') {
          $value = NULL;
        }
      });
      $form_state->setValue(['task', 'settings'], $values);
      $task_form_state = SubformState::createForSubform($form['task']['settings'], $form, $form_state);
      $task->submitConfigurationForm($form['task']['settings'], $task_form_state);
    }
    if ($form_state->hasValue(['subject', 'settings']) && $subject instanceof PluginFormInterface) {
      $values = $form_state->getValue(['subject', 'settings']);
      array_walk_recursive($values, function (&$value) {
        if ($value === '_none') {
          $value = NULL;
        }
      });
      $form_state->setValue(['subject', 'settings'], $values);
      $subject_form_state = SubformState::createForSubform($form['subject']['settings'], $form, $form_state);
      $subject->submitConfigurationForm($form['subject']['settings'], $subject_form_state);
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if (!$this->flow->access('update')) {
      $form_state->setError($form, $this->t('You don\'t have permission to manage this configuration.'));
    }

    if ($triggering_element = &$form_state->getTriggeringElement()) {
      if (isset($triggering_element['#parents']) && reset($triggering_element['#parents']) !== 'actions') {
        return;
      }
    }

    $subject = $this->subject;
    $task = $this->task;
    if ($subject instanceof PluginFormInterface) {
      $subject_form_state = SubformState::createForSubform($form['subject']['settings'], $form, $form_state);
      $subject->validateConfigurationForm($form['subject']['settings'], $subject_form_state);
    }
    if ($task instanceof PluginFormInterface) {
      $task_form_state = SubformState::createForSubform($form['task']['settings'], $form, $form_state);
      $task->validateConfigurationForm($form['task']['settings'], $task_form_state);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    if (!$this->flow->access('update')) {
      return;
    }
    if ($triggering_element = &$form_state->getTriggeringElement()) {
      if (isset($triggering_element['#parents']) && reset($triggering_element['#parents']) !== 'actions') {
        return;
      }
    }

    $subject = $this->subject;
    $task = $this->task;
    if (isset($form['subject']['settings']) && $subject instanceof PluginFormInterface) {
      $subject_form_state = SubformState::createForSubform($form['subject']['settings'], $form, $form_state);
      $subject->submitConfigurationForm($form['subject']['settings'], $subject_form_state);
    }
    if (isset($form['task']['settings']) && $task instanceof PluginFormInterface) {
      $task_form_state = SubformState::createForSubform($form['task']['settings'], $form, $form_state);
      $task->submitConfigurationForm($form['task']['settings'], $task_form_state);
    }
  }

  /**
   * Redirect after save submission callback.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function redirectAfterSave(array &$form, FormStateInterface $form_state) {
    if (!$this->flow->access('update')) {
      return;
    }

    $config = $this->flow;
    $task_modes = FlowTaskMode::service()->getAvailableTaskModes();

    $t_args = [
      '%label' => $config->isCustom() ? $config->get('custom')['label'] : $task_modes[$config->getTaskMode()],
      '%type' =>$this->entityTypeManager->getDefinition($config->getTargetEntityTypeId())->getLabel(),
    ];
    $message = $config->isCustom() ? $this->t('The custom %label flow configuration for %type has been saved.', $t_args)
      : $this->t('The %label flow configuration for %type has been saved.', $t_args);

    $this->messenger->addStatus($message);

    $bundle_type_id = $this->targetEntityType->getBundleEntityType() ?: 'bundle';

    if ($this->savedNewTask) {
      $this->messenger->addWarning($this->t("The newly added task is not yet enabled. <a href=\":url\">Enable it now</a>, or enable it later by choosing \"Enable\" in the operations column below on this page.", [
        ':url' => Url::fromRoute("flow.task.{$this->targetEntityType->id()}.enable", [
          'entity_type_id' => $this->targetEntityType->id(),
          $bundle_type_id => $this->flow->getTargetBundle(),
          'flow_task_mode' => $this->flow->getTaskMode(),
          'flow_task_index' => $this->taskIndex,
        ])->toString(),
      ]));
    }

    $form_state->setRedirect("entity.flow.{$this->targetEntityType->id()}.task_mode", [
      'entity_type_id' => $this->targetEntityType->id(),
      $bundle_type_id => $this->flow->getTargetBundle(),
      'flow_task_mode' => $this->flow->getTaskMode(),
    ]);
  }

  /**
   * Save submission callback.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function save(array &$form, FormStateInterface $form_state): void {
    if (!$this->flow->access('update')) {
      return;
    }
    $flow = $this->flow;
    $task = $this->task;
    $subject = $this->subject;
    $tasks_array = $flow->get('tasks');
    $task_is_new = !($this->taskIndex < $this->flow->getTasks()->count());
    $tasks_array[$this->taskIndex] = [
      'id' => $task->getPluginId(),
      'type' => $task->getBaseId(),
      'weight' => $this->taskIndex,
      'active' => !$task_is_new && !empty($task->getConfiguration()['active']),
      'execution' => $form_state->getValue('execution', ['start' => 'now']),
      'subject' => [
        'id' => $subject->getPluginId(),
        'type' => $subject->getBaseId(),
        'settings' => $subject->getSettings(),
        'third_party_settings' => [],
      ],
      'settings' => $task->getSettings(),
      'third_party_settings' => [],
    ];
    foreach ($task->getThirdPartyProviders() as $provider) {
      $tasks_array[$this->taskIndex]['third_party_settings'][$provider] = $task->getThirdPartySettings($provider);
    }
    foreach ($subject->getThirdPartyProviders() as $provider) {
      $tasks_array[$this->taskIndex]['subject']['third_party_settings'][$provider] = $subject->getThirdPartySettings($provider);
    }
    $this->filterRuntimeSettings($tasks_array);
    $flow->setTasks($tasks_array);
    $flow->save();
    $this->savedNewTask = $task_is_new;
  }

  /**
   * Delete submission callback that redirects to the task delete form.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function delete(array &$form, FormStateInterface $form_state): void {
    $flow = $this->flow;
    $target_type = $this->targetEntityType;
    $bundle_type_id = $target_type->getBundleEntityType() ?: 'bundle';
    $form_state->setRedirect("flow.task.{$target_type->id()}.delete", [
      'entity_type_id' => $target_type->id(),
      $bundle_type_id => $flow->getTargetBundle(),
      'flow_task_mode' => $flow->getTaskMode(),
      'flow_task_index' => $this->taskIndex,
    ]);
  }

  /**
   * Initializes the form object properties.
   *
   * @param array &$form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param \Drupal\flow\Entity\FlowInterface|null $flow
   *   The Flow config entity.
   * @param \Drupal\flow\Plugin\FlowTaskInterface|null $task
   *   The Flow task plugin.
   * @param \Drupal\flow\Plugin\FlowSubjectInterface|null $subject
   *   The Flow subject plugin.
   * @param int|null $task_index
   *   The position of the Flow task within the tasks list of the Flow config.
   */
  protected function initProperties(array &$form, FormStateInterface $form_state, ?FlowInterface $flow = NULL, ?FlowTaskInterface $task = NULL, ?FlowSubjectInterface $subject = NULL, ?int $task_index = NULL): void {
    if ($form_state->has('flow')) {
      $this->flow = $form_state->get('flow');
      $this->task = $form_state->get('task');
      $this->subject = $form_state->get('subject');
      $this->taskIndex = $form_state->get('task_index');
    }
    elseif (isset($flow, $task, $subject, $task_index)) {
      $this->flow = $flow;
      $this->task = $task;
      $this->subject = $subject;
      $this->taskIndex = $task_index;
    }
    elseif ($config_values = $form_state->getValue('config')) {
      $config_values = $form_state->getValue('config');
      $this->flow = Flow::getFlow($config_values['entity_type'], $config_values['bundle'], $config_values['task_mode']);
      $tasks = $this->flow->getTasks();
      $subjects = $this->flow->getSubjects();
      if ($tasks->has($config_values['task_index'])) {
        $this->task = $tasks->get($config_values['task_index']);
        $this->subject = $subjects->get($config_values['task_index']);
      }
      else {
        $flow_keys = [
          'entity_type_id' => $this->flow->getTargetEntityTypeId(),
          'bundle' => $this->flow->getTargetBundle(),
          'task_mode' => $this->flow->getTaskMode(),
        ];
        /** @var \Drupal\flow\Plugin\FlowTaskManager $task_manager */
        $task_manager = \Drupal::service('plugin.manager.flow.task');
        $this->task = $task_manager->createInstance($config_values['task_plugin_id'], $flow_keys);
        /** @var \Drupal\flow\Plugin\FlowSubjectManager $subject_manager */
        $subject_manager = \Drupal::service('plugin.manager.flow.subject');
        $this->subject = $subject_manager->createInstance($config_values['subject_plugin_id'], $flow_keys);
      }
      $this->taskIndex = $config_values['task_index'];
    }
    else {
      throw new \InvalidArgumentException("Form build error: The Flow task plugin form cannot be built without any information about according configuration.");
    }
    if (!FlowCompatibility::validate($this->flow, $this->task, $this->subject)) {
      throw new \InvalidArgumentException('Form build error: The Flow task form cannot not be built with incompatible components.');
    }
    $this->targetEntityType = $this->entityTypeManager->getDefinition($this->flow->getTargetEntityTypeId());
    $form_state->set('flow', $this->flow);
    $form_state->set('task', $this->task);
    $form_state->set('subject', $this->subject);
    $form_state->set('task_index', $this->taskIndex);
  }

  /**
   * Filters runtime settings from the given array.
   *
   * @param array &$array
   *   The array.
   */
  protected function filterRuntimeSettings(&$array) {
    foreach ($array as $k => $v) {
      if ($k === 'target_for' || $k === 'subject_for') {
        unset($array[$k]);
      }
      elseif (is_array($v)) {
        $this->filterRuntimeSettings($array[$k]);
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc