diff --git a/core/modules/workflows/src/Form/DialogFormTrait.php b/core/modules/workflows/src/Form/DialogFormTrait.php index 102dee1f5f..d483b4f570 100644 --- a/core/modules/workflows/src/Form/DialogFormTrait.php +++ b/core/modules/workflows/src/Form/DialogFormTrait.php @@ -2,8 +2,6 @@ namespace Drupal\workflows\Form; -use Drupal\Component\Utility\Html; -use Drupal\Core\Ajax\RedirectCommand; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\Core\Ajax\AjaxResponse; @@ -13,51 +11,11 @@ * Provides a utility trait to simplify rendering forms in a dialog. * * @internal + * + * @todo Move to \Drupal\Core in https://www.drupal.org/node/2896535. */ trait DialogFormTrait { - /** - * Adds dialog support to a form. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - protected function buildFormDialog(array &$form, FormStateInterface $form_state) { - if ($this->getRequestWrapperFormat() !== 'drupal_modal') { - return; - } - - $form['actions']['submit']['#ajax'] = [ - 'dialogType' => 'modal', - 'callback' => '::submitFormDialog', - ]; - - $form['actions']['cancel'] = [ - '#type' => 'link', - '#title' => $this->t('Cancel'), - '#url' => isset($this->workflow) ? $this->workflow->toUrl('edit-form') : $this->getEntity()->toUrl('edit-form'), - '#weight' => 100, - '#attributes' => [ - 'class' => ['button', 'dialog-cancel'], - ], - ]; - - $form['#attached']['library'][] = 'core/drupal.dialog.ajax'; - - // static::submitFormDialog() requires data-drupal-selector to be the same - // between the various Ajax requests. A bug in - // \Drupal\Core\Form\FormBuilder prevents that from happening unless - // $form['#id'] is also the same. Normally, #id is set to a unique HTML ID - // via Html::getUniqueId(), but here we bypass that in order to work around - // the data-drupal-selector bug. This is okay so long as we assume that this - // form only ever occurs once on a page. - // @todo Remove this workaround once https://www.drupal.org/node/2897377 is - // fixed. - $form['#id'] = Html::getId($form_state->getBuildInfo()['form_id']); - } - /** * Submit form dialog #ajax callback. * @@ -67,35 +25,60 @@ protected function buildFormDialog(array &$form, FormStateInterface $form_state) * The current state of the form. * * @return \Drupal\Core\Ajax\AjaxResponse - * An AJAX response that display validation error messages or redirects - * to a URL. + * An AJAX response that display validation error messages or represents a + * successful submission. */ - public function submitFormDialog(array &$form, FormStateInterface $form_state) { - $response = new AjaxResponse(); + public function ajaxSubmit(array &$form, FormStateInterface $form_state) { if ($form_state->hasAnyErrors()) { $form['status_messages'] = [ '#type' => 'status_messages', '#weight' => -1000, ]; + $response = new AjaxResponse(); $response->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form)); } else { - /** @var \Drupal\workflows\WorkflowInterface $workflow */ - $workflow = $this->workflow ?: $this->getEntity(); - $response->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString())); + $response = $this->successfulAjaxSubmit($form, $form_state); } return $response; } /** - * Gets the request wrapper format. + * Allows the form to respond to a successful AJAX submission. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @return \Drupal\Core\Ajax\AjaxResponse + * An AJAX response. + */ + abstract protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state); + + /** + * Determines if the current request is via AJAX. + * + * @return bool + * TRUE if the current request is via AJAX, FALSE otherwise. + */ + protected function isAjax() { + return in_array($this->getRequestWrapperFormat(), [ + 'drupal_ajax', + 'drupal_dialog', + 'drupal_dialog.off_canvas', + 'drupal_modal', + ]); + } + + /** + * Gets the wrapper format of the current request. * - * @return string - * The request wrapper format. + * @string + * The wrapper format. */ protected function getRequestWrapperFormat() { - return $this->getRequest() - ->get(MainContentViewSubscriber::WRAPPER_FORMAT); + return \Drupal::request()->get(MainContentViewSubscriber::WRAPPER_FORMAT); } } diff --git a/core/modules/workflows/src/Form/WorkflowEntityFormBase.php b/core/modules/workflows/src/Form/WorkflowEntityFormBase.php index a99403d08e..29e76f2d58 100644 --- a/core/modules/workflows/src/Form/WorkflowEntityFormBase.php +++ b/core/modules/workflows/src/Form/WorkflowEntityFormBase.php @@ -2,6 +2,9 @@ namespace Drupal\workflows\Form; +use Drupal\Component\Utility\Html; +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\RedirectCommand; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; @@ -17,7 +20,19 @@ class WorkflowEntityFormBase extends EntityForm { */ public function buildForm(array $form, FormStateInterface $form_state, $workflow_transition = NULL) { $form = parent::buildForm($form, $form_state); - $this->buildFormDialog($form, $form_state, TRUE); + + if ($this->isAjax()) { + $form['actions']['submit']['#ajax'] = ['callback' => '::ajaxSubmit']; + $form['actions']['cancel'] = [ + '#type' => 'link', + '#title' => $this->t('Cancel'), + '#url' => isset($this->workflow) ? $this->workflow->toUrl('edit-form') : $this->getEntity()->toUrl('edit-form'), + '#weight' => 100, + '#attributes' => [ + 'class' => ['button', 'dialog-cancel'], + ], + ]; + } return $form; } @@ -30,4 +45,15 @@ public function actions(array $form, FormStateInterface $form_state) { return $actions; } + /** + * {@inheritdoc} + */ + protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) { + /** @var \Drupal\workflows\WorkflowInterface $workflow */ + $workflow = $this->workflow ?: $this->getEntity(); + $response = new AjaxResponse(); + $response->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString())); + return $response; + } + } diff --git a/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php index e178fe40ad..7e2bfd9303 100644 --- a/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php +++ b/core/modules/workflows/src/Form/WorkflowStateDeleteForm.php @@ -2,6 +2,8 @@ namespace Drupal\workflows\Form; +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\RedirectCommand; use Drupal\workflows\WorkflowInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; @@ -87,8 +89,11 @@ public function buildForm(array $form, FormStateInterface $form_state, WorkflowI } $form = parent::buildForm($form, $form_state); - $this->buildFormDialog($form, $form_state, TRUE); + if ($this->isAjax()) { + $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['cancel']['#attributes']['class'][] = 'dialog-cancel'; + } return $form; } @@ -111,4 +116,16 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($this->getCancelUrl()); } + /** + * {@inheritdoc} + */ + protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) { + /** @var \Drupal\workflows\WorkflowInterface $workflow */ + $workflow = $this->workflow ?: $this->getEntity(); + $response = new AjaxResponse(); + $response->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString())); + return $response; + } + + } diff --git a/core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php b/core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php index 26f69f85f5..be246a6349 100644 --- a/core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php +++ b/core/modules/workflows/src/Form/WorkflowTransitionDeleteForm.php @@ -2,6 +2,8 @@ namespace Drupal\workflows\Form; +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\RedirectCommand; use Drupal\workflows\WorkflowInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; @@ -91,7 +93,11 @@ public function buildForm(array $form, FormStateInterface $form_state, WorkflowI $this->workflow = $workflow; $form = parent::buildForm($form, $form_state); - $this->buildFormDialog($form, $form_state, TRUE); + + if ($this->isAjax()) { + $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['cancel']['#attributes']['class'][] = 'dialog-cancel'; + } return $form; } @@ -108,4 +114,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($this->getCancelUrl()); } + /** + * {@inheritdoc} + */ + protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) { + /** @var \Drupal\workflows\WorkflowInterface $workflow */ + $workflow = $this->workflow ?: $this->getEntity(); + $response = new AjaxResponse(); + $response->addCommand(new RedirectCommand($workflow->toUrl('edit-form')->setAbsolute()->toString())); + return $response; + } + }