Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / entityqueue / src / Form / EntitySubqueueForm.php
1 <?php
2
3 namespace Drupal\entityqueue\Form;
4
5 use Drupal\Component\Datetime\TimeInterface;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Component\Utility\NestedArray;
8 use Drupal\Core\Entity\ContentEntityForm;
9 use Drupal\Core\Entity\EntityManagerInterface;
10 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
11 use Drupal\Core\Field\WidgetBase;
12 use Drupal\Core\Form\FormStateInterface;
13 use Drupal\Core\Render\ElementInfoManagerInterface;
14 use Drupal\inline_entity_form\Plugin\Field\FieldWidget\InlineEntityFormBase;
15 use Psr\Log\LoggerInterface;
16 use Symfony\Component\DependencyInjection\ContainerInterface;
17
18 /**
19  * Form controller for the entity subqueue edit forms.
20  */
21 class EntitySubqueueForm extends ContentEntityForm {
22
23   /**
24    * The entity being used by this form.
25    *
26    * @var \Drupal\entityqueue\EntitySubqueueInterface
27    */
28   protected $entity;
29
30   /**
31    * The element info manager.
32    *
33    * @var \Drupal\Core\Render\ElementInfoManagerInterface
34    */
35   protected $elementInfo;
36
37   /**
38    * A logger instance.
39    *
40    * @var \Psr\Log\LoggerInterface
41    */
42   protected $logger;
43
44   /**
45    * {@inheritdoc}
46    */
47   public static function create(ContainerInterface $container) {
48     return new static(
49       $container->get('entity.manager'),
50       $container->get('entity_type.bundle.info'),
51       $container->get('datetime.time'),
52       $container->get('element_info'),
53       $container->get('logger.factory')->get('entityqueue')
54     );
55   }
56
57   /**
58    * Constructs a EntitySubqueueForm.
59    *
60    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
61    *   The entity manager.
62    * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
63    *   The entity type bundle service.
64    * @param \Drupal\Component\Datetime\TimeInterface $time
65    *   The time service.
66    * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
67    *   The element info manager.
68    * @param \Psr\Log\LoggerInterface $logger
69    *   A logger instance.
70    */
71   public function __construct(EntityManagerInterface $entity_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time, ElementInfoManagerInterface $element_info, LoggerInterface $logger) {
72     parent::__construct($entity_manager, $entity_type_bundle_info, $time);
73
74     $this->elementInfo = $element_info;
75     $this->logger = $logger;
76   }
77
78   /**
79    * {@inheritdoc}
80    */
81   public function form(array $form, FormStateInterface $form_state) {
82     // Reverse the items in the admin form if the queue uses the 'Reverse order
83     // in admin view' option.
84     if ($this->entity->getQueue()->getReverseInAdmin()) {
85       $subqueue_items = $this->entity->get('items');
86       $items_values = $subqueue_items->getValue();
87       $subqueue_items->setValue(array_reverse($items_values));
88     }
89
90     $form = parent::form($form, $form_state);
91
92     $form['#title'] = $this->t('Edit subqueue %label', ['%label' => $this->entity->label()]);
93
94     // Since the form has ajax buttons, the $wrapper_id will change each time
95     // one of those buttons is clicked. Therefore the whole form has to be
96     // replaced, otherwise the buttons will have the old $wrapper_id and will
97     // only work on the first click.
98     if ($form_state->has('subqueue_form_wrapper_id')) {
99       $wrapper_id = $form_state->get('subqueue_form_wrapper_id');
100     }
101     else {
102       $wrapper_id = Html::getUniqueId($this->getFormId() . '-wrapper');
103     }
104
105     $form_state->set('subqueue_form_wrapper_id', $wrapper_id);
106     $form['#prefix'] = '<div id="' . $wrapper_id . '">';
107     $form['#suffix'] = '</div>';
108
109     // @todo Use the 'Machine name' field widget when
110     //   https://www.drupal.org/node/2685749 is committed.
111     $element_info = $this->elementInfo->getInfo('machine_name');
112     $form['name'] = [
113       '#type' => 'machine_name',
114       '#default_value' => $this->entity->id(),
115       '#source_field' => 'title',
116       '#process' => array_merge([[get_class($this), 'processMachineNameSource']], $element_info['#process']),
117       '#machine_name' => [
118         'exists' => '\Drupal\entityqueue\Entity\EntitySubqueue::load',
119       ],
120       '#disabled' => !$this->entity->isNew(),
121       '#weight' => -5,
122       '#access' => !$this->entity->getQueue()->getHandlerPlugin()->hasAutomatedSubqueues(),
123     ];
124
125     return $form;
126   }
127
128   /**
129    * Form API callback: Sets the 'source' property of a machine_name element.
130    *
131    * This method is assigned as a #process callback in formElement() method.
132    */
133   public static function processMachineNameSource($element, FormStateInterface $form_state, $form) {
134     $source_field_state = WidgetBase::getWidgetState($form['#parents'], $element['#source_field'], $form_state);
135
136     // Hide the field widget if the source field is not configured properly or
137     // if it doesn't exist in the form.
138     if (empty($element['#source_field']) || empty($source_field_state['array_parents'])) {
139       $element['#access'] = FALSE;
140     }
141     else {
142       $source_field_element = NestedArray::getValue($form_state->getCompleteForm(), $source_field_state['array_parents']);
143       $element['#machine_name']['source'] = $source_field_element[0]['value']['#array_parents'];
144     }
145
146     return $element;
147   }
148
149   /**
150    * {@inheritdoc}
151    */
152   protected function actions(array $form, FormStateInterface $form_state) {
153     $actions = parent::actions($form, $form_state);
154
155     $actions['reverse'] = [
156       '#type' => 'submit',
157       '#value' => $this->t('Reverse'),
158       '#submit' => ['::submitAction'],
159       '#op' => 'reverse',
160       '#ajax' => [
161         'callback' => '::subqueueActionAjaxForm',
162         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
163       ],
164     ];
165
166     $actions['shuffle'] = [
167       '#type' => 'submit',
168       '#value' => $this->t('Shuffle'),
169       '#submit' => ['::submitAction'],
170       '#op' => 'shuffle',
171       '#ajax' => [
172         'callback' => '::subqueueActionAjaxForm',
173         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
174       ],
175     ];
176
177     $actions['clear'] = [
178       '#type' => 'submit',
179       '#value' => $this->t('Clear'),
180       '#submit' => ['::submitAction'],
181       '#op' => 'clear',
182       '#ajax' => [
183         'callback' => '::subqueueActionAjaxForm',
184         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
185       ],
186     ];
187
188     return $actions;
189   }
190
191   /**
192    * Submit callback for the 'reverse', 'shuffle' and 'clear' actions.
193    */
194   public static function submitAction(array &$form, FormStateInterface $form_state) {
195     $trigger = $form_state->getTriggeringElement();
196     $op = $trigger['#op'];
197
198     // Check if we have a form element for the 'items' field.
199     $path = array_merge($form['#parents'], ['items']);
200     $key_exists = NULL;
201     NestedArray::getValue($form_state->getValues(), $path, $key_exists);
202
203     if ($key_exists) {
204       // Remove any user input for the 'items' element in order to allow the
205       // values set below to be applied.
206       $user_input = $form_state->getUserInput();
207       NestedArray::setValue($user_input, $path, NULL);
208       $form_state->setUserInput($user_input);
209
210       $entity = $form_state->getFormObject()->getEntity();
211       $items_widget = $form_state->getFormObject()->getFormDisplay($form_state)->getRenderer('items');
212
213       $subqueue_items = $entity->get('items');
214       $items_widget->extractFormValues($subqueue_items, $form, $form_state);
215       $items_values = $subqueue_items->getValue();
216
217       // Revert the effect of the 'Reverse order in admin view' option.
218       if ($entity->getQueue()->getReverseInAdmin()) {
219         $items_values = array_reverse($items_values);
220       }
221
222       switch ($op) {
223         case 'reverse':
224           $subqueue_items->setValue(array_reverse($items_values));
225           break;
226
227         case 'shuffle':
228           shuffle($items_values);
229           $subqueue_items->setValue($items_values);
230           break;
231
232         case 'clear':
233           $subqueue_items->setValue(NULL);
234           break;
235       }
236
237       // Handle 'inline_entity_form' widgets separately because they have a
238       // custom form state storage for the current state of the referenced
239       // entities.
240       if (\Drupal::moduleHandler()->moduleExists('inline_entity_form') && $items_widget instanceof InlineEntityFormBase) {
241         $items_form_element = NestedArray::getValue($form, $path);
242         $ief_id = $items_form_element['widget']['#ief_id'];
243
244         $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
245
246         if (isset($entities)) {
247           $form_state->set(['inline_entity_form', $ief_id, 'entities'], []);
248
249           switch ($op) {
250             case 'reverse':
251               $entities = array_reverse($entities);
252               break;
253
254             case 'shuffle':
255               shuffle($entities);
256               break;
257
258             case 'clear':
259               $entities = [];
260               break;
261           }
262
263           foreach ($entities as $delta => $item) {
264             $item['_weight'] = $delta;
265             $form_state->set(['inline_entity_form', $ief_id, 'entities', $delta], $item);
266           }
267         }
268       }
269
270       $form_state->getFormObject()->setEntity($entity);
271
272       $form_state->setRebuild();
273     }
274   }
275
276   /**
277    * AJAX callback; Returns the entire form element.
278    */
279   public static function subqueueActionAjaxForm(array &$form, FormStateInterface $form_state) {
280     return $form;
281   }
282
283   /**
284    * {@inheritdoc}
285    */
286   public function save(array $form, FormStateInterface $form_state) {
287     $subqueue = $this->entity;
288
289     // Revert the effect of the 'Reverse order in admin view' option.
290     if ($subqueue->getQueue()->getReverseInAdmin()) {
291       $subqueue_items = $subqueue->get('items');
292       $items_values = $subqueue_items->getValue();
293       $subqueue_items->setValue(array_reverse($items_values));
294     }
295
296     $status = $subqueue->save();
297
298     $edit_link = $subqueue->toLink($this->t('Edit'), 'edit-form')->toString();
299     if ($status == SAVED_UPDATED) {
300       drupal_set_message($this->t('The entity subqueue %label has been updated.', ['%label' => $subqueue->label()]));
301       $this->logger->notice('The entity subqueue %label has been updated.', ['%label' => $subqueue->label(), 'link' => $edit_link]);
302     }
303     else {
304       drupal_set_message($this->t('The entity subqueue %label has been added.', ['%label' => $subqueue->label()]));
305       $this->logger->notice('The entity subqueue %label has been added.', ['%label' => $subqueue->label(), 'link' => $edit_link]);
306     }
307
308     $queue = $subqueue->getQueue();
309     if ($queue->getHandlerPlugin()->supportsMultipleSubqueues()) {
310       $form_state->setRedirectUrl($queue->toUrl('subqueue-list'));
311     }
312     else {
313       $form_state->setRedirectUrl($queue->toUrl('collection'));
314     }
315   }
316
317 }