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\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;
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
33 * @var \Psr\Log\LoggerInterface
40 public static function create(ContainerInterface $container) {
42 $container->get('entity.manager'),
43 $container->get('logger.factory')->get('entityqueue')
48 * Constructs a EntitySubqueueForm.
50 * @param \Psr\Log\LoggerInterface $logger
53 public function __construct(EntityManagerInterface $entity_manager, LoggerInterface $logger) {
54 parent::__construct($entity_manager);
56 $this->logger = $logger;
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));
71 $form = parent::form($form, $form_state);
73 $form['#title'] = $this->t('Edit subqueue %label', ['%label' => $this->entity->label()]);
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');
83 $wrapper_id = Html::getUniqueId($this->getFormId() . '-wrapper');
86 $form_state->set('subqueue_form_wrapper_id', $wrapper_id);
87 $form['#prefix'] = '<div id="' . $wrapper_id . '">';
88 $form['#suffix'] = '</div>';
90 // @todo Consider creating a 'Machine name' field widget.
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'],
98 '#disabled' => !$this->entity->isNew(),
100 '#access' => !$this->entity->getQueue()->getHandlerPlugin()->hasAutomatedSubqueues(),
109 protected function actions(array $form, FormStateInterface $form_state) {
110 $actions = parent::actions($form, $form_state);
112 $actions['reverse'] = [
114 '#value' => $this->t('Reverse'),
115 '#submit' => ['::submitAction'],
118 'callback' => '::subqueueActionAjaxForm',
119 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
123 $actions['shuffle'] = [
125 '#value' => $this->t('Shuffle'),
126 '#submit' => ['::submitAction'],
129 'callback' => '::subqueueActionAjaxForm',
130 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
134 $actions['clear'] = [
136 '#value' => $this->t('Clear'),
137 '#submit' => ['::submitAction'],
140 'callback' => '::subqueueActionAjaxForm',
141 'wrapper' => $form_state->get('subqueue_form_wrapper_id'),
149 * Submit callback for the 'reverse', 'shuffle' and 'clear' actions.
151 public static function submitAction(array &$form, FormStateInterface $form_state) {
152 $trigger = $form_state->getTriggeringElement();
153 $op = $trigger['#op'];
155 // Check if we have a form element for the 'items' field.
156 $path = array_merge($form['#parents'], ['items']);
158 NestedArray::getValue($form_state->getValues(), $path, $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);
167 $entity = $form_state->getFormObject()->getEntity();
168 $items_widget = $form_state->getFormObject()->getFormDisplay($form_state)->getRenderer('items');
170 $subqueue_items = $entity->get('items');
171 $items_widget->extractFormValues($subqueue_items, $form, $form_state);
172 $items_values = $subqueue_items->getValue();
174 // Revert the effect of the 'Reverse order in admin view' option.
175 if ($entity->getQueue()->getReverseInAdmin()) {
176 $items_values = array_reverse($items_values);
181 $subqueue_items->setValue(array_reverse($items_values));
185 shuffle($items_values);
186 $subqueue_items->setValue($items_values);
190 $subqueue_items->setValue(NULL);
194 // Handle 'inline_entity_form' widgets separately because they have a
195 // custom form state storage for the current state of the referenced
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'];
201 $entities = $form_state->get(['inline_entity_form', $ief_id, 'entities']);
203 if (isset($entities)) {
204 $form_state->set(['inline_entity_form', $ief_id, 'entities'], []);
208 $entities = array_reverse($entities);
220 foreach ($entities as $delta => $item) {
221 $item['_weight'] = $delta;
222 $form_state->set(['inline_entity_form', $ief_id, 'entities', $delta], $item);
227 $form_state->getFormObject()->setEntity($entity);
229 $form_state->setRebuild();
234 * AJAX callback; Returns the entire form element.
236 public static function subqueueActionAjaxForm(array &$form, FormStateInterface $form_state) {
243 public function save(array $form, FormStateInterface $form_state) {
244 $subqueue = $this->entity;
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));
253 $status = $subqueue->save();
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]);
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]);
265 $queue = $subqueue->getQueue();
266 if ($queue->getHandlerPlugin()->supportsMultipleSubqueues()) {
267 $form_state->setRedirectUrl($queue->toUrl('subqueue-list'));
270 $form_state->setRedirectUrl($queue->toUrl('collection'));
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);