84522929892a0278ac89bdd53ea5cb49d441a55b
[yaffs-website] / web / core / modules / workflows / src / Form / WorkflowTransitionAddForm.php
1 <?php
2
3 namespace Drupal\workflows\Form;
4
5 use Drupal\Core\Entity\EntityForm;
6 use Drupal\Core\Entity\EntityInterface;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Form\SubformState;
9 use Drupal\Core\Plugin\PluginFormFactoryInterface;
10 use Drupal\workflows\State;
11 use Drupal\workflows\TransitionInterface;
12 use Symfony\Component\DependencyInjection\ContainerInterface;
13
14 /**
15  * Class WorkflowTransitionAddForm.
16  */
17 class WorkflowTransitionAddForm extends EntityForm {
18
19   /**
20    * The plugin form factory.
21    *
22    * @var \Drupal\Core\Plugin\PluginFormFactoryInterface
23    */
24   protected $pluginFormFactory;
25
26   /**
27    * Creates an instance of WorkflowStateEditForm.
28    *
29    * @param \Drupal\Core\Plugin\PluginFormFactoryInterface $pluginFormFactory
30    *   The plugin form factory.
31    */
32   public function __construct(PluginFormFactoryInterface $pluginFormFactory) {
33     $this->pluginFormFactory = $pluginFormFactory;
34   }
35
36   /**
37    * {@inheritdoc}
38    */
39   public static function create(ContainerInterface $container) {
40     return new static(
41       $container->get('plugin_form.factory')
42     );
43   }
44
45   /**
46    * {@inheritdoc}
47    */
48   public function getFormId() {
49     return 'workflow_transition_add_form';
50   }
51
52   /**
53    * {@inheritdoc}
54    */
55   public function form(array $form, FormStateInterface $form_state) {
56     $form = parent::form($form, $form_state);
57
58     /* @var \Drupal\workflows\WorkflowInterface $workflow */
59     $workflow = $this->getEntity();
60     $workflow_type = $workflow->getTypePlugin();
61
62     $form['label'] = [
63       '#type' => 'textfield',
64       '#title' => $this->t('Label'),
65       '#maxlength' => 255,
66       '#default_value' => '',
67       '#description' => $this->t('Label for the transition.'),
68       '#required' => TRUE,
69     ];
70
71     $form['id'] = [
72       '#type' => 'machine_name',
73       '#machine_name' => [
74         'exists' => [$this, 'exists'],
75       ],
76     ];
77
78     // @todo https://www.drupal.org/node/2830584 Add some ajax to ensure that
79     //   only valid transitions are selectable.
80     $states = array_map([State::class, 'labelCallback'], $workflow->getTypePlugin()->getStates());
81     $form['from'] = [
82       '#type' => 'checkboxes',
83       '#title' => $this->t('From'),
84       '#required' => TRUE,
85       '#default_value' => [],
86       '#options' => $states,
87     ];
88     $form['to'] = [
89       '#type' => 'radios',
90       '#title' => $this->t('To'),
91       '#required' => TRUE,
92       '#options' => $states,
93     ];
94
95     // Add additional form fields from the workflow type plugin.
96     if ($workflow_type->hasFormClass(TransitionInterface::PLUGIN_FORM_KEY)) {
97       $form['type_settings'] = [
98         '#tree' => TRUE,
99       ];
100       $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
101       $form['type_settings'] += $this->pluginFormFactory
102         ->createInstance($workflow_type, TransitionInterface::PLUGIN_FORM_KEY)
103         ->buildConfigurationForm($form['type_settings'], $subform_state);
104     }
105
106     return $form;
107   }
108
109   /**
110    * Determines if the workflow transition already exists.
111    *
112    * @param string $transition_id
113    *   The workflow transition ID.
114    *
115    * @return bool
116    *   TRUE if the workflow transition exists, FALSE otherwise.
117    */
118   public function exists($transition_id) {
119     /** @var \Drupal\workflows\WorkflowInterface $original_workflow */
120     $original_workflow = \Drupal::entityTypeManager()->getStorage('workflow')->loadUnchanged($this->getEntity()->id());
121     return $original_workflow->getTypePlugin()->hasTransition($transition_id);
122   }
123
124   /**
125    * Copies top-level form values to entity properties
126    *
127    * This form can only change values for a state, which is part of workflow.
128    *
129    * @param \Drupal\Core\Entity\EntityInterface $entity
130    *   The entity the current form should operate upon.
131    * @param array $form
132    *   A nested array of form elements comprising the form.
133    * @param \Drupal\Core\Form\FormStateInterface $form_state
134    *   The current state of the form.
135    */
136   protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) {
137     if (!$form_state->isValidationComplete()) {
138       // Only do something once form validation is complete.
139       return;
140     }
141     /** @var \Drupal\workflows\WorkflowInterface $entity */
142     $values = $form_state->getValues();
143     $entity->getTypePlugin()->addTransition($values['id'], $values['label'], array_filter($values['from']), $values['to']);
144   }
145
146   /**
147    * {@inheritdoc}
148    */
149   public function validateForm(array &$form, FormStateInterface $form_state) {
150     /** @var \Drupal\workflows\WorkflowInterface $workflow */
151     $workflow = $this->getEntity();
152     $workflow_type = $workflow->getTypePlugin();
153
154     $values = $form_state->getValues();
155     foreach (array_filter($values['from']) as $from_state_id) {
156       if ($workflow->getTypePlugin()->hasTransitionFromStateToState($from_state_id, $values['to'])) {
157         $form_state->setErrorByName('from][' . $from_state_id, $this->t('The transition from %from to %to already exists.', [
158           '%from' => $workflow->getTypePlugin()->getState($from_state_id)->label(),
159           '%to' => $workflow->getTypePlugin()->getState($values['to'])->label(),
160         ]));
161       }
162     }
163
164     if ($workflow_type->hasFormClass(TransitionInterface::PLUGIN_FORM_KEY)) {
165       $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
166       $this->pluginFormFactory
167         ->createInstance($workflow_type, TransitionInterface::PLUGIN_FORM_KEY)
168         ->validateConfigurationForm($form['type_settings'], $subform_state);
169     }
170   }
171
172   /**
173    * {@inheritdoc}
174    */
175   public function save(array $form, FormStateInterface $form_state) {
176     /** @var \Drupal\workflows\WorkflowInterface $workflow */
177     $workflow = $this->entity;
178     $workflow_type = $workflow->getTypePlugin();
179     $transition = $workflow_type->getTransition($form_state->getValue('id'));
180
181     if ($workflow_type->hasFormClass(TransitionInterface::PLUGIN_FORM_KEY)) {
182       $subform_state = SubformState::createForSubform($form['type_settings'], $form, $form_state);
183       $subform_state->set('transition', $transition);
184       $this->pluginFormFactory
185         ->createInstance($workflow_type, TransitionInterface::PLUGIN_FORM_KEY)
186         ->submitConfigurationForm($form['type_settings'], $subform_state);
187     }
188
189     $workflow->save();
190     drupal_set_message($this->t('Created %label transition.', [
191       '%label' => $form_state->getValue('label'),
192     ]));
193     $form_state->setRedirectUrl($workflow->toUrl('edit-form'));
194   }
195
196   /**
197    * {@inheritdoc}
198    */
199   protected function actions(array $form, FormStateInterface $form_state) {
200     $actions['submit'] = [
201       '#type' => 'submit',
202       '#value' => $this->t('Save'),
203       '#submit' => ['::submitForm', '::save'],
204     ];
205     return $actions;
206   }
207
208 }