7837333dcd80e585b0edd61488c3d56cf2901a73
[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\EntityChangedInterface;
10 use Drupal\Core\Entity\EntityInterface;
11 use Drupal\Core\Entity\EntityManagerInterface;
12 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
13 use Drupal\Core\Form\FormStateInterface;
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    * A logger instance.
32    *
33    * @var \Psr\Log\LoggerInterface
34    */
35   protected $logger;
36
37   /**
38    * {@inheritdoc}
39    */
40   public static function create(ContainerInterface $container) {
41     return new static(
42       $container->get('entity.manager'),
43       $container->get('logger.factory')->get('entityqueue')
44     );
45   }
46
47   /**
48    * Constructs a EntitySubqueueForm.
49    *
50    * @param \Psr\Log\LoggerInterface $logger
51    *   A logger instance.
52    */
53   public function __construct(EntityManagerInterface $entity_manager, LoggerInterface $logger) {
54     parent::__construct($entity_manager);
55
56     $this->logger = $logger;
57   }
58
59   /**
60    * {@inheritdoc}
61    */
62   public function form(array $form, FormStateInterface $form_state) {
63     // Reverse the items in the admin form if the queue uses the 'Reverse order
64     // in admin view' option.
65     if ($this->entity->getQueue()->getReverseInAdmin()) {
66       $subqueue_items = $this->entity->get('items');
67       $items_values = $subqueue_items->getValue();
68       $subqueue_items->setValue(array_reverse($items_values));
69     }
70
71     $form = parent::form($form, $form_state);
72
73     $form['#title'] = $this->t('Edit subqueue %label', ['%label' => $this->entity->label()]);
74
75     // Since the form has ajax buttons, the $wrapper_id will change each time
76     // one of those buttons is clicked. Therefore the whole form has to be
77     // replaced, otherwise the buttons will have the old $wrapper_id and will
78     // only work on the first click.
79     if ($form_state->has('subqueue_form_wrapper_id')) {
80       $wrapper_id = $form_state->get('subqueue_form_wrapper_id');
81     }
82     else {
83       $wrapper_id = Html::getUniqueId($this->getFormId() . '-wrapper');
84     }
85
86     $form_state->set('subqueue_form_wrapper_id', $wrapper_id);
87     $form['#prefix'] = '<div id="' . $wrapper_id . '">';
88     $form['#suffix'] = '</div>';
89
90     // @todo Consider creating a 'Machine name' field widget.
91     $form['name'] = [
92       '#type' => 'machine_name',
93       '#default_value' => $this->entity->id(),
94       '#machine_name' => array(
95         'exists' => '\Drupal\entityqueue\Entity\EntitySubqueue::load',
96         'source' => ['title', 'widget', 0, 'value'],
97       ),
98       '#disabled' => !$this->entity->isNew(),
99       '#weight' => -5,
100       '#access' => !$this->entity->getQueue()->getHandlerPlugin()->hasAutomatedSubqueues(),
101     ];
102
103     return $form;
104   }
105
106   /**
107    * {@inheritdoc}
108    */
109   protected function actions(array $form, FormStateInterface $form_state) {
110     $actions = parent::actions($form, $form_state);
111
112     $actions['reverse'] = [
113       '#type' => 'submit',
114       '#value' => $this->t('Reverse'),
115       '#submit' => ['::submitAction'],
116       '#op' => 'reverse',
117       '#ajax' => [
118         'callback' => '::subqueueActionAjaxForm',
119         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
120       ],
121     ];
122
123     $actions['shuffle'] = [
124       '#type' => 'submit',
125       '#value' => $this->t('Shuffle'),
126       '#submit' => ['::submitAction'],
127       '#op' => 'shuffle',
128       '#ajax' => [
129         'callback' => '::subqueueActionAjaxForm',
130         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
131       ],
132     ];
133
134     $actions['clear'] = [
135       '#type' => 'submit',
136       '#value' => $this->t('Clear'),
137       '#submit' => ['::submitAction'],
138       '#op' => 'clear',
139       '#ajax' => [
140         'callback' => '::subqueueActionAjaxForm',
141         'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
142       ],
143     ];
144
145     return $actions;
146   }
147
148   /**
149    * Submit callback for the 'reverse', 'shuffle' and 'clear' actions.
150    */
151   public static function submitAction(array &$form, FormStateInterface $form_state) {
152     $trigger = $form_state->getTriggeringElement();
153     $op = $trigger['#op'];
154
155     // Check if we have a form element for the 'items' field.
156     $path = array_merge($form['#parents'], ['items']);
157     $key_exists = NULL;
158     NestedArray::getValue($form_state->getValues(), $path, $key_exists);
159
160     if ($key_exists) {
161       // Remove any user input for the 'items' element in order to allow the
162       // values set below to be applied.
163       $user_input = $form_state->getUserInput();
164       NestedArray::setValue($user_input, $path, NULL);
165       $form_state->setUserInput($user_input);
166
167       $entity = $form_state->getFormObject()->getEntity();
168       $items_widget = $form_state->getFormObject()->getFormDisplay($form_state)->getRenderer('items');
169
170       $subqueue_items = $entity->get('items');
171       $items_widget->extractFormValues($subqueue_items, $form, $form_state);
172       $items_values = $subqueue_items->getValue();
173
174       // Revert the effect of the 'Reverse order in admin view' option.
175       if ($entity->getQueue()->getReverseInAdmin()) {
176         $items_values = array_reverse($items_values);
177       }
178
179       switch ($op) {
180         case 'reverse':
181           $subqueue_items->setValue(array_reverse($items_values));
182           break;
183
184         case 'shuffle':
185           shuffle($items_values);
186           $subqueue_items->setValue($items_values);
187           break;
188
189         case 'clear':
190           $subqueue_items->setValue(NULL);
191           break;
192       }
193
194       // Handle 'inline_entity_form' widgets separately because they have a
195       // custom form state storage for the current state of the referenced
196       // entities.
197       if (\Drupal::moduleHandler()->moduleExists('inline_entity_form') && $items_widget instanceof InlineEntityFormBase) {
198         $items_form_element = NestedArray::getValue($form, $path);
199         $ief_id = $items_form_element['widget']['#ief_id'];
200
201         $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
202
203         if (isset($entities)) {
204           $form_state->set(['inline_entity_form', $ief_id, 'entities'], []);
205
206           switch ($op) {
207             case 'reverse':
208               $entities = array_reverse($entities);
209               break;
210
211             case 'shuffle':
212               shuffle($entities);
213               break;
214
215             case 'clear':
216               $entities = [];
217               break;
218           }
219
220           foreach ($entities as $delta => $item) {
221             $item['_weight'] = $delta;
222             $form_state->set(['inline_entity_form', $ief_id, 'entities', $delta], $item);
223           }
224         }
225       }
226
227       $form_state->getFormObject()->setEntity($entity);
228
229       $form_state->setRebuild();
230     }
231   }
232
233   /**
234    * AJAX callback; Returns the entire form element.
235    */
236   public static function subqueueActionAjaxForm(array &$form, FormStateInterface $form_state) {
237     return $form;
238   }
239
240   /**
241    * {@inheritdoc}
242    */
243   public function save(array $form, FormStateInterface $form_state) {
244     $subqueue = $this->entity;
245
246     // Revert the effect of the 'Reverse order in admin view' option.
247     if ($subqueue->getQueue()->getReverseInAdmin()) {
248       $subqueue_items = $subqueue->get('items');
249       $items_values = $subqueue_items->getValue();
250       $subqueue_items->setValue(array_reverse($items_values));
251     }
252
253     $status = $subqueue->save();
254
255     $edit_link = $subqueue->toLink($this->t('Edit'), 'edit-form')->toString();
256     if ($status == SAVED_UPDATED) {
257       drupal_set_message($this->t('The entity subqueue %label has been updated.', ['%label' => $subqueue->label()]));
258       $this->logger->notice('The entity subqueue %label has been updated.', ['%label' => $subqueue->label(), 'link' => $edit_link]);
259     }
260     else {
261       drupal_set_message($this->t('The entity subqueue %label has been added.', ['%label' => $subqueue->label()]));
262       $this->logger->notice('The entity subqueue %label has been added.', ['%label' => $subqueue->label(), 'link' =>  $edit_link]);
263     }
264
265     $queue = $subqueue->getQueue();
266     if ($queue->getHandlerPlugin()->supportsMultipleSubqueues()) {
267       $form_state->setRedirectUrl($queue->toUrl('subqueue-list'));
268     }
269     else {
270       $form_state->setRedirectUrl($queue->toUrl('collection'));
271     }
272   }
273
274   /**
275    * {@inheritdoc}
276    */
277   public function updateChangedTime(EntityInterface $entity) {
278     // @todo Remove this method when Drupal 8.2.x is no longer supported.
279     if ($entity->getEntityType()->isSubclassOf(EntityChangedInterface::class)) {
280       $entity->setChangedTime(REQUEST_TIME);
281     }
282   }
283
284 }