1<?php
2
3namespace Drupal\workflows\Form;
4
5use Drupal\Core\Entity\EntityForm;
6use Drupal\Core\Entity\EntityInterface;
7use Drupal\Core\Form\FormStateInterface;
8use Drupal\Core\Form\SubformState;
9use Drupal\Core\Plugin\PluginFormFactoryInterface;
10use Drupal\workflows\StateInterface;
11use Symfony\Component\DependencyInjection\ContainerInterface;
12
13/**
14 * Class WorkflowStateAddForm.
15 *
16 * @internal
17 */
18class WorkflowStateAddForm extends EntityForm {
19
20  /**
21   * The plugin form factory.
22   *
23   * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
24   */
25  protected $pluginFormFactory;
26
27  /**
28   * Creates an instance of WorkflowStateEditForm.
29   *
30   * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $pluginFormFactory
31   *   The plugin form factory.
32   */
33  public function __construct(PluginFormFactoryInterface $pluginFormFactory) {
34    $this->pluginFormFactory = $pluginFormFactory;
35  }
36
37  /**
38   * {@inheritdoc}
39   */
40  public static function create(ContainerInterface $container) {
41    return new static(
42      $container->get('plugin_form.factory')
43    );
44  }
45
46  /**
47   * {@inheritdoc}
48   */
49  public function getFormId() {
50    return 'workflow_state_add_form';
51  }
52
53  /**
54   * {@inheritdoc}
55   */
56  public function form(array $form, FormStateInterface $form_state) {
57    $form = parent::form($form, $form_state);
58
59    /* @var \Drupal\workflows\WorkflowInterface $workflow */
60    $workflow = $this->getEntity();
61    $workflow_type = $workflow->getTypePlugin();
62
63    $form['label'] = [
64      '#type' => 'textfield',
65      '#title' => $this->t('State label'),
66      '#maxlength' => 255,
67      '#default_value' => '',
68      '#required' => TRUE,
69    ];
70
71    $form['id'] = [
72      '#type' => 'machine_name',
73      '#machine_name' => [
74        'exists' => [$this, 'exists'],
75      ],
76    ];
77
78    if ($workflow_type->hasFormClass(StateInterface::PLUGIN_FORM_KEY)) {
79      $form['type_settings'] = [
80        '#tree' => TRUE,
81      ];
82      $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
83      $form['type_settings'] += $this->pluginFormFactory
84        ->createInstance($workflow_type, StateInterface::PLUGIN_FORM_KEY)
85        ->buildConfigurationForm($form['type_settings'], $subform_state);
86    }
87
88    return $form;
89  }
90
91  /**
92   * Determines if the workflow state already exists.
93   *
94   * @param string $state_id
95   *   The workflow state ID.
96   *
97   * @return bool
98   *   TRUE if the workflow state exists, FALSE otherwise.
99   */
100  public function exists($state_id) {
101    /** @var \Drupal\workflows\WorkflowInterface $original_workflow */
102    $original_workflow = \Drupal::entityTypeManager()->getStorage('workflow')->loadUnchanged($this->getEntity()->id());
103    return $original_workflow->getTypePlugin()->hasState($state_id);
104  }
105
106  /**
107   * Copies top-level form values to entity properties
108   *
109   * This form can only change values for a state, which is part of workflow.
110   *
111   * @param \Drupal\Core\Entity\EntityInterface $entity
112   *   The entity the current form should operate upon.
113   * @param array $form
114   *   A nested array of form elements comprising the form.
115   * @param \Drupal\Core\Form\FormStateInterface $form_state
116   *   The current state of the form.
117   */
118  protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) {
119    if (!$form_state->isValidationComplete()) {
120      // Only do something once form validation is complete.
121      return;
122    }
123    /** @var \Drupal\workflows\WorkflowInterface $entity */
124    $values = $form_state->getValues();
125    $entity->getTypePlugin()->addState($values['id'], $values['label']);
126  }
127
128  /**
129   * {@inheritdoc}
130   */
131  public function validateForm(array &$form, FormStateInterface $form_state) {
132    parent::validateForm($form, $form_state);
133    /** @var \Drupal\workflows\WorkflowTypeInterface $workflow_type */
134    $workflow = $this->entity;
135    $workflow_type = $workflow->getTypePlugin();
136
137    if ($workflow_type->hasFormClass(StateInterface::PLUGIN_FORM_KEY)) {
138      $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
139      $this->pluginFormFactory
140        ->createInstance($workflow_type, StateInterface::PLUGIN_FORM_KEY)
141        ->validateConfigurationForm($form['type_settings'], $subform_state);
142    }
143  }
144
145  /**
146   * {@inheritdoc}
147   */
148  public function save(array $form, FormStateInterface $form_state) {
149    /** @var \Drupal\workflows\WorkflowInterface $workflow */
150    $workflow = $this->entity;
151    $workflow_type = $workflow->getTypePlugin();
152    $state = $workflow_type->getState($form_state->getValue('id'));
153
154    if ($workflow_type->hasFormClass(StateInterface::PLUGIN_FORM_KEY)) {
155      $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
156      $subform_state->set('state', $state);
157      $this->pluginFormFactory
158        ->createInstance($workflow_type, StateInterface::PLUGIN_FORM_KEY)
159        ->submitConfigurationForm($form['type_settings'], $subform_state);
160    }
161
162    $workflow->save();
163    $this->messenger()->addStatus($this->t('Created %label state.', [
164      '%label' => $workflow->getTypePlugin()->getState($form_state->getValue('id'))->label(),
165    ]));
166    $form_state->setRedirectUrl($workflow->toUrl('edit-form'));
167  }
168
169  /**
170   * {@inheritdoc}
171   */
172  protected function actions(array $form, FormStateInterface $form_state) {
173    $actions['submit'] = [
174      '#type' => 'submit',
175      '#value' => $this->t('Save'),
176      '#submit' => ['::submitForm', '::save'],
177    ];
178    return $actions;
179  }
180
181}
182