3 namespace Drupal\entityqueue\Form;
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;
19 * Form controller for the entity subqueue edit forms.
21 class EntitySubqueueForm extends ContentEntityForm {
24 * The entity being used by this form.
26 * @var \Drupal\entityqueue\EntitySubqueueInterface
31 * The element info manager.
33 * @var \Drupal\Core\Render\ElementInfoManagerInterface
35 protected $elementInfo;
40 * @var \Psr\Log\LoggerInterface
47 public static function create(ContainerInterface $container) {
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')
58 * Constructs a EntitySubqueueForm.
60 * @param \Drupal\Core\Entity\EntityManagerInterface $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
66 * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
67 * The element info manager.
68 * @param \Psr\Log\LoggerInterface $logger
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);
74 $this->elementInfo = $element_info;
75 $this->logger = $logger;
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));
90 $form = parent::form($form, $form_state);
92 $form['#title'] = $this->t('Edit subqueue %label', ['%label' => $this->entity->label()]);
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');
102 $wrapper_id = Html::getUniqueId($this->getFormId() . '-wrapper');
105 $form_state->set('subqueue_form_wrapper_id', $wrapper_id);
106 $form['#prefix'] = '<div id="' . $wrapper_id . '">';
107 $form['#suffix'] = '</div>';
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');
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']),
118 'exists' => '\Drupal\entityqueue\Entity\EntitySubqueue::load',
120 '#disabled' => !$this->entity->isNew(),
122 '#access' => !$this->entity->getQueue()->getHandlerPlugin()->hasAutomatedSubqueues(),
129 * Form API callback: Sets the 'source' property of a machine_name element.
131 * This method is assigned as a #process callback in formElement() method.
133 public static function processMachineNameSource($element, FormStateInterface $form_state, $form) {
134 $source_field_state = WidgetBase::getWidgetState($form['#parents'], $element['#source_field'], $form_state);
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;
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'];
152 protected function actions(array $form, FormStateInterface $form_state) {
153 $actions = parent::actions($form, $form_state);
155 $actions['reverse'] = [
157 '#value' => $this->t('Reverse'),
158 '#submit' => ['::submitAction'],
161 'callback' => '::subqueueActionAjaxForm',
162 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
166 $actions['shuffle'] = [
168 '#value' => $this->t('Shuffle'),
169 '#submit' => ['::submitAction'],
172 'callback' => '::subqueueActionAjaxForm',
173 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
177 $actions['clear'] = [
179 '#value' => $this->t('Clear'),
180 '#submit' => ['::submitAction'],
183 'callback' => '::subqueueActionAjaxForm',
184 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
192 * Submit callback for the 'reverse', 'shuffle' and 'clear' actions.
194 public static function submitAction(array &$form, FormStateInterface $form_state) {
195 $trigger = $form_state->getTriggeringElement();
196 $op = $trigger['#op'];
198 // Check if we have a form element for the 'items' field.
199 $path = array_merge($form['#parents'], ['items']);
201 NestedArray::getValue($form_state->getValues(), $path, $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);
210 $entity = $form_state->getFormObject()->getEntity();
211 $items_widget = $form_state->getFormObject()->getFormDisplay($form_state)->getRenderer('items');
213 $subqueue_items = $entity->get('items');
214 $items_widget->extractFormValues($subqueue_items, $form, $form_state);
215 $items_values = $subqueue_items->getValue();
217 // Revert the effect of the 'Reverse order in admin view' option.
218 if ($entity->getQueue()->getReverseInAdmin()) {
219 $items_values = array_reverse($items_values);
224 $subqueue_items->setValue(array_reverse($items_values));
228 shuffle($items_values);
229 $subqueue_items->setValue($items_values);
233 $subqueue_items->setValue(NULL);
237 // Handle 'inline_entity_form' widgets separately because they have a
238 // custom form state storage for the current state of the referenced
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'];
244 $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
246 if (isset($entities)) {
247 $form_state->set(['inline_entity_form', $ief_id, 'entities'], []);
251 $entities = array_reverse($entities);
263 foreach ($entities as $delta => $item) {
264 $item['_weight'] = $delta;
265 $form_state->set(['inline_entity_form', $ief_id, 'entities', $delta], $item);
270 $form_state->getFormObject()->setEntity($entity);
272 $form_state->setRebuild();
277 * AJAX callback; Returns the entire form element.
279 public static function subqueueActionAjaxForm(array &$form, FormStateInterface $form_state) {
286 public function save(array $form, FormStateInterface $form_state) {
287 $subqueue = $this->entity;
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));
296 $status = $subqueue->save();
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]);
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]);
308 $queue = $subqueue->getQueue();
309 if ($queue->getHandlerPlugin()->supportsMultipleSubqueues()) {
310 $form_state->setRedirectUrl($queue->toUrl('subqueue-list'));
313 $form_state->setRedirectUrl($queue->toUrl('collection'));