From 18ddb0044c8b935a7a2037de0189cc85435c3d2b Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Thu, 7 Aug 2014 21:43:27 +0100 Subject: [PATCH] Issue #2315807 by tim.plunkett: Remove support for path-based form redirects. --- core/includes/batch.inc | 16 ++++--- core/includes/form.inc | 2 +- core/lib/Drupal/Core/Annotation/Action.php | 5 +-- core/lib/Drupal/Core/Form/FormState.php | 34 ++++---------- .../Drupal/Core/Form/FormStateInterface.php | 4 -- core/lib/Drupal/Core/Form/FormSubmitter.php | 39 +++------------- .../Core/Form/FormSubmitterInterface.php | 39 ++++------------ .../src/ContentTranslationHandler.php | 16 ++++--- core/modules/field_ui/src/FieldOverview.php | 8 +--- core/modules/field_ui/src/FieldUI.php | 6 ++- .../src/Form/FieldInstanceEditForm.php | 7 +-- .../src/Form/FieldStorageEditForm.php | 7 +-- core/modules/file/file.module | 2 +- .../node/src/Plugin/Action/DeleteNode.php | 2 +- core/modules/path/src/Form/DeleteForm.php | 2 +- .../src/Plugin/views/field/BulkForm.php | 4 +- core/modules/system/system.module | 20 ++++++--- .../ajax_test/src/Form/AjaxTestDialogForm.php | 2 +- .../src/Form/FormTestCheckboxesZeroForm.php | 2 +- .../src/Form/FormTestRedirectForm.php | 7 ++- .../taxonomy/src/Form/OverviewTerms.php | 1 - core/modules/taxonomy/src/TermForm.php | 4 -- .../update/src/Form/UpdateManagerInstall.php | 2 +- core/modules/update/src/Form/UpdateReady.php | 2 +- .../user/src/Plugin/Action/CancelUser.php | 2 +- core/modules/user/src/RegisterForm.php | 6 --- .../exposed_form/ExposedFormPluginBase.php | 1 - core/modules/views_ui/src/ViewEditForm.php | 37 +++++++++------ .../Tests/Core/Form/FormBuilderTest.php | 2 +- .../Drupal/Tests/Core/Form/FormStateTest.php | 8 +--- .../Tests/Core/Form/FormSubmitterTest.php | 45 +++++-------------- 31 files changed, 118 insertions(+), 216 deletions(-) diff --git a/core/includes/batch.inc b/core/includes/batch.inc index 11362208c91..e1565a55661 100644 --- a/core/includes/batch.inc +++ b/core/includes/batch.inc @@ -16,9 +16,11 @@ use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Timer; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Batch\Percentage; use Drupal\Core\Form\FormState; use Drupal\Core\Page\DefaultHtmlPageRenderer; +use Drupal\Core\Url; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -446,13 +448,15 @@ function _batch_finished() { if (!isset($_batch['form_state'])) { $_batch['form_state'] = new FormState(); } - if (!isset($_batch['form_state']['redirect'])) { - if (isset($_batch['redirect'])) { - $_batch['form_state']['redirect'] = $_batch['redirect']; - } - else { - $_batch['form_state']['redirect'] = $_batch['source_url']; + if ($_batch['form_state']->getRedirect() === NULL) { + $redirect = $_batch['batch_redirect'] ?: $_batch['source_url']; + $options = UrlHelper::parse($redirect); + if (!UrlHelper::isExternal($options['path'])) { + $options['path'] = $GLOBALS['base_url'] . '/' . $options['path']; } + $redirect = Url::createFromPath($options['path']); + $redirect->setOptions($options); + $_batch['form_state']->setRedirectUrl($redirect); } // Use \Drupal\Core\Form\FormSubmitterInterface::redirectForm() to handle diff --git a/core/includes/form.inc b/core/includes/form.inc index 5a24e985a7a..1b4a086f584 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -3066,7 +3066,7 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = NU 'url' => $url, 'url_options' => array(), 'source_url' => current_path(), - 'redirect' => $redirect, + 'batch_redirect' => $redirect, 'theme' => $GLOBALS['theme_key'], 'redirect_callback' => $redirect_callback, ); diff --git a/core/lib/Drupal/Core/Annotation/Action.php b/core/lib/Drupal/Core/Annotation/Action.php index 0e4fd737e39..5d0937dd409 100644 --- a/core/lib/Drupal/Core/Annotation/Action.php +++ b/core/lib/Drupal/Core/Annotation/Action.php @@ -42,14 +42,13 @@ class Action extends Plugin { public $label; /** - * The path for a confirmation form for this action. + * The route name for a confirmation form for this action. * - * @todo Change this to accept a route. * @todo Provide a more generic way to allow an action to be confirmed first. * * @var string (optional) */ - public $confirm_form_path = ''; + public $confirm_form_route_name = ''; /** * The entity type the action can apply to. diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php index 5733d5a4bad..5e2be94ef80 100644 --- a/core/lib/Drupal/Core/Form/FormState.php +++ b/core/lib/Drupal/Core/Form/FormState.php @@ -111,34 +111,26 @@ class FormState implements FormStateInterface, \ArrayAccess { * Used when a form needs to return some kind of a * \Symfony\Component\HttpFoundation\Response object, e.g., a * \Symfony\Component\HttpFoundation\BinaryFileResponse when triggering a - * file download. If you use the $form_state['redirect'] key, it will be used - * to build a \Symfony\Component\HttpFoundation\RedirectResponse and will - * populate this key. + * file download. If you use self::setRedirect() or self::setRedirectUrl(), + * it will be used to build a + * \Symfony\Component\HttpFoundation\RedirectResponse and will populate this + * key. * * @var \Symfony\Component\HttpFoundation\Response|null */ protected $response; /** - * Used to redirect the form on submission. It may either be a string - * containing the destination URL, or an array of arguments compatible with - * url(). See url() for complete information. + * Used to redirect the form on submission. + * + * @see self::getRedirect() * * This property is uncacheable. * - * @var string|array|null + * @var \Drupal\Core\Url|\Symfony\Component\HttpFoundation\RedirectResponse|null */ protected $redirect; - /** - * Used for route-based redirects. - * - * This property is uncacheable. - * - * @var \Drupal\Core\Url|array - */ - protected $redirect_route; - /** * If set to TRUE the form will NOT perform a redirect, even if * self::$redirect is set. @@ -611,7 +603,7 @@ class FormState implements FormStateInterface, \ArrayAccess { * {@inheritdoc} */ public function setRedirectUrl(Url $url) { - $this->set('redirect_route', $url); + $this->set('redirect', $url); return $this; } @@ -633,14 +625,6 @@ class FormState implements FormStateInterface, \ArrayAccess { return FALSE; } - // Check for a route-based redirection. - if ($redirect_route = $this->get('redirect_route')) { - $redirect_route->setAbsolute(); - return $redirect_route; - } - - // @todo Remove once all redirects are converted away from paths in - // https://www.drupal.org/node/2315807. return $this->get('redirect'); } diff --git a/core/lib/Drupal/Core/Form/FormStateInterface.php b/core/lib/Drupal/Core/Form/FormStateInterface.php index c7868cbefec..a24d28dc0df 100644 --- a/core/lib/Drupal/Core/Form/FormStateInterface.php +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php @@ -127,10 +127,6 @@ interface FormStateInterface { * The value will be one of the following: * - A fully prepared \Symfony\Component\HttpFoundation\RedirectResponse. * - An instance of \Drupal\Core\Url to use for the redirect. - * - A numerically-indexed array where the first value is the path to use - * for the redirect, and the optional second value is an array of options - * for generating the URL from the path. - * - The path to use for the redirect. * - NULL, to signify that no redirect was specified and that the current * path should be used for the redirect. * - FALSE, to signify that no redirect should take place. diff --git a/core/lib/Drupal/Core/Form/FormSubmitter.php b/core/lib/Drupal/Core/Form/FormSubmitter.php index fb447a2974f..e99727e6040 100644 --- a/core/lib/Drupal/Core/Form/FormSubmitter.php +++ b/core/lib/Drupal/Core/Form/FormSubmitter.php @@ -127,10 +127,6 @@ class FormSubmitter implements FormSubmitterInterface { * {@inheritdoc} */ public function redirectForm(FormStateInterface $form_state) { - // According to RFC 7231, 303 See Other status code must be used to redirect - // user agent (and not default 302 Found). - // @see http://tools.ietf.org/html/rfc7231#section-6.4.4 - $status_code = Response::HTTP_SEE_OTHER; $redirect = $form_state->getRedirect(); // Allow using redirect responses directly if needed. @@ -141,35 +137,7 @@ class FormSubmitter implements FormSubmitterInterface { $url = NULL; // Check for a route-based redirection. if ($redirect instanceof Url) { - $url = $redirect->toString(); - } - // An array contains the path to use for the redirect, as well as options to - // use for generating the URL. - elseif (is_array($redirect)) { - if (isset($redirect[1])) { - $options = $redirect[1]; - } - else { - $options = array(); - } - // Redirections should always use absolute URLs. - $options['absolute'] = TRUE; - if (isset($redirect[2])) { - $status_code = $redirect[2]; - } - $url = $this->urlGenerator->generateFromPath($redirect[0], $options); - } - // A string represents the path to use for the redirect. - elseif (is_string($redirect)) { - // This function can be called from the installer, which guarantees - // that $redirect will always be a string, so catch that case here - // and use the appropriate redirect function. - if ($this->drupalInstallationAttempted()) { - install_goto($redirect); - } - else { - $url = $this->urlGenerator->generateFromPath($redirect, array('absolute' => TRUE)); - } + $url = $redirect->setAbsolute()->toString(); } // If no redirect was specified, redirect to the current path. elseif ($redirect === NULL) { @@ -183,7 +151,10 @@ class FormSubmitter implements FormSubmitterInterface { } if ($url) { - return new RedirectResponse($url, $status_code); + // According to RFC 7231, 303 See Other status code must be used to redirect + // user agent (and not default 302 Found). + // @see http://tools.ietf.org/html/rfc7231#section-6.4.4 + return new RedirectResponse($url, Response::HTTP_SEE_OTHER); } } diff --git a/core/lib/Drupal/Core/Form/FormSubmitterInterface.php b/core/lib/Drupal/Core/Form/FormSubmitterInterface.php index 8a79fe0791d..15ce4d21246 100644 --- a/core/lib/Drupal/Core/Form/FormSubmitterInterface.php +++ b/core/lib/Drupal/Core/Form/FormSubmitterInterface.php @@ -49,21 +49,18 @@ interface FormSubmitterInterface { * destination should be, based on the $form_state and the 'destination' * query string in the request URL, and redirects the user there. * - * Usually (for exceptions, see below) $form_state['redirect'] determines - * where to redirect the user. This can be set either to a string (the path to - * redirect to), or an array of arguments for url(). If - * $form_state['redirect'] is missing, the user is usually (again, see below - * for exceptions) redirected back to the page they came from, where they - * should see a fresh, unpopulated copy of the form. + * The result of \Drupal\Core\Form|FormStateInterface::getRedirect() + * determines where to redirect the user. See the possible return values + * listed there. If the result is FALSE, then the user will not be redirected. * - * Here is an example of how to set up a form to redirect to the path 'node': + * Here is an example of how to set up a form to redirect to the path 'user': * @code - * $form_state->set('redirect', 'node'); + * $form_state->setRedirect('user.page'); * @endcode * And here is an example of how to redirect to 'node/123?foo=bar#baz': * @code - * $form_state->set('redirect', array( - * 'node/123', + * $form_state->setRedirect('node.view', + * array('node' => 123), * array( * 'query' => array( * 'foo' => 'bar', @@ -73,27 +70,7 @@ interface FormSubmitterInterface { * )); * @endcode * - * There are several exceptions to the "usual" behavior described above: - * - If $form_state['programmed'] is TRUE, the form submission was usually - * invoked via self::submitForm(), so any redirection would break the script - * that invoked self::submitForm() and no redirection is done. - * - If $form_state['rebuild'] is TRUE, the form is being rebuilt, and no - * redirection is done. - * - If $form_state['no_redirect'] is TRUE, redirection is disabled. This is - * set, for instance, by \Drupal\system\FormAjaxController::getForm() to - * prevent redirection in Ajax callbacks. $form_state['no_redirect'] should - * never be set or altered by form builder functions or form validation - * or submit handlers. - * - If $form_state['redirect'] is set to FALSE, redirection is disabled. - * - If none of the above conditions has prevented redirection, then the - * redirect is accomplished by returning a RedirectResponse, passing in the - * value of $form_state['redirect'] if it is set, or the current path if it - * is not. RedirectResponse preferentially uses the value of - * \Drupal::request->query->get('destination') (the 'destination' URL query - * string) if it is present, so this will override any values set by - * $form_state['redirect']. - * - * @param $form_state + * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @return \Symfony\Component\HttpFoundation\RedirectResponse|null diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index d7601e73d64..b1b7cc079b3 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -435,8 +435,12 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface { $entity = $form_controller->getEntity(); $source = $form_state['values']['source_langcode']['source']; - $path = $entity->getSystemPath('drupal:content-translation-overview'); - $form_state['redirect'] = $path . '/add/' . $source . '/' . $form_controller->getFormLangcode($form_state); + $entity_type_id = $entity->getEntityTypeId(); + $form_state->setRedirect('content_translation.translation_add_' . $entity_type_id, array( + $entity_type_id => $entity->id(), + 'source' => $source, + 'target' => $form_controller->getFormLangcode($form_state), + )); $languages = language_list(); drupal_set_message(t('Source language set to: %language', array('%language' => $languages[$source]->name))); } @@ -462,9 +466,11 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface { function entityFormDeleteTranslation($form, FormStateInterface $form_state) { $form_controller = content_translation_form_controller($form_state); $entity = $form_controller->getEntity(); - $path = $entity->getSystemPath('drupal:content-translation-overview'); - $form_langcode = $form_controller->getFormLangcode($form_state); - $form_state['redirect'] = $path . '/delete/' . $form_langcode; + $entity_type_id = $entity->getEntityTypeId(); + $form_state->setRedirect('content_translation.delete_' . $entity_type_id, array( + $entity_type_id => $entity->id(), + 'language' => $form_controller->getFormLangcode($form_state), + )); } /** diff --git a/core/modules/field_ui/src/FieldOverview.php b/core/modules/field_ui/src/FieldOverview.php index 4cea5072b8c..04c9805aa84 100644 --- a/core/modules/field_ui/src/FieldOverview.php +++ b/core/modules/field_ui/src/FieldOverview.php @@ -478,13 +478,7 @@ class FieldOverview extends OverviewBase { if ($destinations) { $destination = drupal_get_destination(); $destinations[] = $destination['destination']; - $next_destination = FieldUI::getNextDestination($destinations, $form_state); - if (isset($next_destination['route_name'])) { - $form_state->setRedirect($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); - } - else { - $form_state['redirect'] = $next_destination; - } + $form_state->setRedirectUrl(FieldUI::getNextDestination($destinations, $form_state)); } elseif (!$error) { drupal_set_message($this->t('Your settings have been saved.')); diff --git a/core/modules/field_ui/src/FieldUI.php b/core/modules/field_ui/src/FieldUI.php index 77773985e39..bd180106408 100644 --- a/core/modules/field_ui/src/FieldUI.php +++ b/core/modules/field_ui/src/FieldUI.php @@ -41,7 +41,7 @@ class FieldUI { * @param array $destinations * An array of destinations to redirect to. * - * @return array + * @return \Drupal\Core\Url * The next destination to redirect to. */ public static function getNextDestination(array $destinations) { @@ -51,13 +51,15 @@ class FieldUI { $next_destination += array( 'route_parameters' => array(), ); + $next_destination = new Url($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); } else { $options = UrlHelper::parse($next_destination); if ($destinations) { $options['query']['destinations'] = $destinations; } - $next_destination = array($options['path'], $options); + $next_destination = Url::createFromPath($options['path']); + $next_destination->setOptions($options); } return $next_destination; } diff --git a/core/modules/field_ui/src/Form/FieldInstanceEditForm.php b/core/modules/field_ui/src/Form/FieldInstanceEditForm.php index 3aacd3ce2c7..08bb37bb8bb 100644 --- a/core/modules/field_ui/src/Form/FieldInstanceEditForm.php +++ b/core/modules/field_ui/src/Form/FieldInstanceEditForm.php @@ -195,12 +195,7 @@ class FieldInstanceEditForm extends FormBase { $request = $this->getRequest(); if (($destinations = $request->query->get('destinations')) && $next_destination = FieldUI::getNextDestination($destinations)) { $request->query->remove('destinations'); - if (isset($next_destination['route_name'])) { - $form_state->setRedirect($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); - } - else { - $form_state['redirect'] = $next_destination; - } + $form_state->setRedirectUrl($next_destination); } else { $form_state->setRedirectUrl(FieldUI::getOverviewRouteInfo($this->instance->entity_type, $this->instance->bundle)); diff --git a/core/modules/field_ui/src/Form/FieldStorageEditForm.php b/core/modules/field_ui/src/Form/FieldStorageEditForm.php index d7d0aa34f91..81306703e95 100644 --- a/core/modules/field_ui/src/Form/FieldStorageEditForm.php +++ b/core/modules/field_ui/src/Form/FieldStorageEditForm.php @@ -198,12 +198,7 @@ class FieldStorageEditForm extends FormBase { $request = $this->getRequest(); if (($destinations = $request->query->get('destinations')) && $next_destination = FieldUI::getNextDestination($destinations)) { $request->query->remove('destinations'); - if (isset($next_destination['route_name'])) { - $form_state->setRedirect($next_destination['route_name'], $next_destination['route_parameters'], $next_destination['options']); - } - else { - $form_state['redirect'] = $next_destination; - } + $form_state->setRedirectUrl($next_destination); } else { $form_state->setRedirectUrl(FieldUI::getOverviewRouteInfo($this->instance->entity_type, $this->instance->bundle)); diff --git a/core/modules/file/file.module b/core/modules/file/file.module index a48a7a78d78..a71340dd21e 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -1418,7 +1418,7 @@ function file_managed_file_submit($form, FormStateInterface $form_state) { // Set the form to rebuild so that $form is correctly updated in response to // processing the file removal. Since this function did not change $form_state // if the upload button was clicked, a rebuild isn't necessary in that - // situation and setting $form_state['redirect'] to FALSE would suffice. + // situation and setting $form_state['no_redirect'] to TRUE would suffice. // However, we choose to always rebuild, to keep the form processing workflow // consistent between the two buttons. $form_state['rebuild'] = TRUE; diff --git a/core/modules/node/src/Plugin/Action/DeleteNode.php b/core/modules/node/src/Plugin/Action/DeleteNode.php index f2793570e23..e71b5815065 100644 --- a/core/modules/node/src/Plugin/Action/DeleteNode.php +++ b/core/modules/node/src/Plugin/Action/DeleteNode.php @@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * id = "node_delete_action", * label = @Translation("Delete selected content"), * type = "node", - * confirm_form_path = "admin/content/node/delete" + * confirm_form_route_name = "node.multiple_delete_confirm" * ) */ class DeleteNode extends ActionBase implements ContainerFactoryPluginInterface { diff --git a/core/modules/path/src/Form/DeleteForm.php b/core/modules/path/src/Form/DeleteForm.php index b253490719c..80251dc38de 100644 --- a/core/modules/path/src/Form/DeleteForm.php +++ b/core/modules/path/src/Form/DeleteForm.php @@ -89,7 +89,7 @@ class DeleteForm extends ConfirmFormBase { public function submitForm(array &$form, FormStateInterface $form_state) { $this->aliasStorage->delete(array('pid' => $this->pathAlias['pid'])); - $form_state['redirect'] = 'admin/config/search/path'; + $form_state->setRedirect('path.admin_overview'); } } diff --git a/core/modules/system/src/Plugin/views/field/BulkForm.php b/core/modules/system/src/Plugin/views/field/BulkForm.php index 9cf68363e0d..c910ba1c5c1 100644 --- a/core/modules/system/src/Plugin/views/field/BulkForm.php +++ b/core/modules/system/src/Plugin/views/field/BulkForm.php @@ -263,8 +263,8 @@ class BulkForm extends FieldPluginBase { $action->execute($entities); $operation_definition = $action->getPluginDefinition(); - if (!empty($operation_definition['confirm_form_path'])) { - $form_state['redirect'] = $operation_definition['confirm_form_path']; + if (!empty($operation_definition['confirm_form_route_name'])) { + $form_state->setRedirect($operation_definition['confirm_form_route_name']); } $count = count(array_filter($form_state['values'][$this->options['id']])); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 976fcc55fba..cad83e53265 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -14,6 +14,7 @@ use Drupal\Core\StringTranslation\TranslationWrapper; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Menu\MenuTreeParameters; use Drupal\block\BlockPluginInterface; +use Drupal\Core\Url; use Drupal\user\UserInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use GuzzleHttp\Exception\RequestException; @@ -790,7 +791,7 @@ function _system_themes_access($theme) { * using the URL from system_authorized_get_url(). Redirecting yourself is * necessary when your authorized operation is being triggered by a form * submit handler, since calling redirecting in a submit handler is a bad - * idea, and you should instead set $form_state['redirect']. + * idea, and you should instead use $form_state->setRedirect(). * * Once the SESSION is setup for the operation and the user is redirected to * authorize.php, they will be prompted for their connection credentials (core @@ -817,14 +818,14 @@ function _system_themes_access($theme) { * not to assume any code exists. Example (system_authorized_run()): * @code * system_authorized_init($callback, $file, $arguments, $page_title); - * return new RedirectResponse(system_authorized_get_url()); + * return new RedirectResponse(system_authorized_get_url()->toString()); * @endcode * Example (update_manager_install_form_submit()): * @code * system_authorized_init('update_authorize_run_install', * drupal_get_path('module', 'update') . '/update.authorize.inc', * $arguments, t('Update manager')); - * $form_state['redirect'] = system_authorized_get_url(); + * $form_state->setRedirectUrl(system_authorized_get_url()); * @endcode * * @param $callback @@ -863,7 +864,7 @@ function system_authorized_init($callback, $file, $arguments = array(), $page_ti * * @param array $options * Optional array of options to pass to url(). - * @return + * @return \Drupal\Core\Url * The full URL to authorize.php, using HTTPS if available. * * @see system_authorized_init() @@ -873,7 +874,10 @@ function system_authorized_get_url(array $options = array()) { // Force HTTPS if available, regardless of what the caller specifies. $options['https'] = TRUE; // Prefix with $base_url so url() treats it as an external link. - return url($base_url . '/core/authorize.php', $options); + $url = Url::createFromPath($base_url . '/core/authorize.php'); + $url_options = $url->getOptions(); + $url->setOptions($options + $url_options); + return $url; } /** @@ -881,6 +885,8 @@ function system_authorized_get_url(array $options = array()) { * * @param array $options * Optional array of options to pass to url(). + * + * @return \Drupal\Core\Url */ function system_authorized_batch_processing_url(array $options = array()) { $options['query'] = array('batch' => '1'); @@ -894,7 +900,7 @@ function system_authorized_batch_processing_url(array $options = array()) { */ function system_authorized_run($callback, $file, $arguments = array(), $page_title = NULL) { system_authorized_init($callback, $file, $arguments, $page_title); - return new RedirectResponse(system_authorized_get_url()); + return new RedirectResponse(system_authorized_get_url()->toString()); } /** @@ -905,7 +911,7 @@ function system_authorized_run($callback, $file, $arguments = array(), $page_tit function system_authorized_batch_process() { $finish_url = system_authorized_get_url(); $process_url = system_authorized_batch_processing_url(); - return batch_process($finish_url, $process_url); + return batch_process($finish_url->toString(), $process_url->toString()); } /** diff --git a/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php b/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php index 5f118172014..22dc4ee616c 100644 --- a/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php +++ b/core/modules/system/tests/modules/ajax_test/src/Form/AjaxTestDialogForm.php @@ -68,7 +68,7 @@ class AjaxTestDialogForm extends FormBase { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - $form_state['redirect'] = 'ajax-test/dialog-contents'; + $form_state->setRedirect('ajax_test.dialog_contents'); } diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php index 70efd25fba7..557fd647fb2 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestCheckboxesZeroForm.php @@ -60,7 +60,7 @@ class FormTestCheckboxesZeroForm extends FormBase { $form_state->setResponse(new JsonResponse($form_state['values'])); } else { - $form_state['redirect'] = FALSE; + $form_state['no_redirect'] = TRUE; } } diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestRedirectForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestRedirectForm.php index 0adc985f5d0..1c6437d5d0d 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestRedirectForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestRedirectForm.php @@ -9,6 +9,7 @@ namespace Drupal\form_test\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Url; /** * Form builder to detect form redirect. @@ -52,10 +53,12 @@ class FormTestRedirectForm extends FormBase { */ public function submitForm(array &$form, FormStateInterface $form_state) { if (!empty($form_state['values']['redirection'])) { - $form_state['redirect'] = !empty($form_state['values']['destination']) ? $form_state['values']['destination'] : NULL; + if (!empty($form_state['values']['destination'])) { + $form_state->setRedirectUrl(Url::createFromPath($GLOBALS['base_url'] . '/' . $form_state['values']['destination'])); + } } else { - $form_state['redirect'] = FALSE; + $form_state['no_redirect'] = TRUE; } } diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php index fd6606ea676..88addad40bb 100644 --- a/core/modules/taxonomy/src/Form/OverviewTerms.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -341,7 +341,6 @@ class OverviewTerms extends FormBase { '#submit' => array(array($this, 'submitReset')), '#value' => $this->t('Reset to alphabetical'), ); - $form_state['redirect'] = array(current_path(), ($page ? array('query' => array('page' => $page)) : array())); } return $form; diff --git a/core/modules/taxonomy/src/TermForm.php b/core/modules/taxonomy/src/TermForm.php index fa2443ee270..1af2453f84b 100644 --- a/core/modules/taxonomy/src/TermForm.php +++ b/core/modules/taxonomy/src/TermForm.php @@ -98,10 +98,6 @@ class TermForm extends ContentEntityForm { '#value' => $term->id(), ); - if ($term->isNew()) { - $form_state['redirect'] = current_path(); - } - return parent::form($form, $form_state, $term); } diff --git a/core/modules/update/src/Form/UpdateManagerInstall.php b/core/modules/update/src/Form/UpdateManagerInstall.php index 5e56c668f3c..58a49a0495b 100644 --- a/core/modules/update/src/Form/UpdateManagerInstall.php +++ b/core/modules/update/src/Form/UpdateManagerInstall.php @@ -216,7 +216,7 @@ class UpdateManagerInstall extends FormBase { // whatever FileTransfer object authorize.php creates for us. else { system_authorized_init('update_authorize_run_install', drupal_get_path('module', 'update') . '/update.authorize.inc', $arguments, $this->t('Update manager')); - $form_state['redirect'] = system_authorized_get_url(); + $form_state->setRedirectUrl(system_authorized_get_url()); } } diff --git a/core/modules/update/src/Form/UpdateReady.php b/core/modules/update/src/Form/UpdateReady.php index 942164a2946..71bb44176bf 100644 --- a/core/modules/update/src/Form/UpdateReady.php +++ b/core/modules/update/src/Form/UpdateReady.php @@ -141,7 +141,7 @@ class UpdateReady extends FormBase { // whatever FileTransfer object authorize.php creates for us. else { system_authorized_init('update_authorize_run_update', drupal_get_path('module', 'update') . '/update.authorize.inc', array($updates), $this->t('Update manager')); - $form_state['redirect'] = system_authorized_get_url(); + $form_state->setRedirectUrl(system_authorized_get_url()); } } } diff --git a/core/modules/user/src/Plugin/Action/CancelUser.php b/core/modules/user/src/Plugin/Action/CancelUser.php index 4246543b91a..6c0e392b0d5 100644 --- a/core/modules/user/src/Plugin/Action/CancelUser.php +++ b/core/modules/user/src/Plugin/Action/CancelUser.php @@ -19,7 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; * id = "user_cancel_user_action", * label = @Translation("Cancel the selected user accounts"), * type = "user", - * confirm_form_path = "admin/people/cancel" + * confirm_form_route_name = "user.multiple_cancel_confirm" * ) */ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface { diff --git a/core/modules/user/src/RegisterForm.php b/core/modules/user/src/RegisterForm.php index f5c31765850..5a6bfb63630 100644 --- a/core/modules/user/src/RegisterForm.php +++ b/core/modules/user/src/RegisterForm.php @@ -60,12 +60,6 @@ class RegisterForm extends AccountForm { // Start with the default user account fields. $form = parent::form($form, $form_state, $account); - if ($admin) { - // Redirect back to page which initiated the create request; usually - // admin/people/create. - $form_state['redirect'] = current_path(); - } - return $form; } diff --git a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php index 276a4dd2d0c..62e80890a8d 100644 --- a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php +++ b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php @@ -325,7 +325,6 @@ abstract class ExposedFormPluginBase extends PluginBase { $this->view->exposed_data = array(); } - $form_state['redirect'] = current_path(); $form_state['values'] = array(); } diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php index 92f22bed8f8..6d42b52ba59 100644 --- a/core/modules/views_ui/src/ViewEditForm.php +++ b/core/modules/views_ui/src/ViewEditForm.php @@ -7,6 +7,7 @@ namespace Drupal\views_ui; +use Drupal\Component\Utility\UrlHelper; use Drupal\Component\Utility\Xss; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\HtmlCommand; @@ -16,6 +17,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; +use Drupal\Core\Url; use Drupal\user\TempStoreFactory; use Drupal\views\Views; use Symfony\Component\HttpFoundation\RequestStack; @@ -324,7 +326,10 @@ class ViewEditForm extends ViewFormBase { $query->remove('destination'); } } - $form_state['redirect'] = $destination; + if (!UrlHelper::isExternal($destination)) { + $destination = $GLOBALS['base_url'] . '/' . $destination; + } + $form_state->setRedirectUrl(Url::createFromPath($destination)); } $view->save(); @@ -778,22 +783,28 @@ class ViewEditForm extends ViewFormBase { * should not yet redirect to the destination. */ public function submitDelayDestination($form, FormStateInterface $form_state) { - $query = $this->requestStack->getCurrentRequest()->query; - // @todo: Revisit this when http://drupal.org/node/1668866 is in. - $destination = $query->get('destination'); - if (isset($destination) && $form_state['redirect'] !== FALSE) { - if (!isset($form_state['redirect'])) { - $form_state['redirect'] = current_path(); + $request = $this->requestStack->getCurrentRequest(); + $destination = $request->query->get('destination'); + + $redirect = $form_state->getRedirect(); + // If there is a destination, and redirects are not explicitly disabled, add + // the destination as a query string to the redirect and suppress it for the + // current request. + if (isset($destination) && $redirect !== FALSE) { + // Create a valid redirect if one does not exist already. + if (!($redirect instanceof Url)) { + $redirect = Url::createFromRequest($request); } - if (is_string($form_state['redirect'])) { - $form_state['redirect'] = array($form_state['redirect']); - } - $options = isset($form_state['redirect'][1]) ? $form_state['redirect'][1] : array(); + + // Add the current destination to the redirect unless one exists already. + $options = $redirect->getOptions(); if (!isset($options['query']['destination'])) { $options['query']['destination'] = $destination; + $redirect->setOptions($options); } - $form_state['redirect'][1] = $options; - $query->remove('destination'); + + $form_state->setRedirectUrl($redirect); + $request->query->remove('destination'); } } diff --git a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php index 144ed65e380..e071ca4dbf9 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormBuilderTest.php @@ -177,7 +177,7 @@ class FormBuilderTest extends FormTestBase { ->will($this->returnCallback(function ($form, FormStateInterface $form_state) use ($response, $redirect) { // Set both the response and the redirect. $form_state->setResponse($response); - $form_state['redirect'] = $redirect; + $form_state->set('redirect', $redirect); })); $form_state = new FormState(); diff --git a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php index a193af45ee5..41882304cba 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormStateTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormStateTest.php @@ -42,20 +42,14 @@ class FormStateTest extends UnitTestCase { $data = array(); $data[] = array(array(), NULL); - $data[] = array(array('redirect' => 'foo'), 'foo'); - $data[] = array(array('redirect' => array('foo')), array('foo')); - $data[] = array(array('redirect' => array('bar', array('query' => array('foo' => 'baz')))), array('bar', array('query' => array('foo' => 'baz')))); - $data[] = array(array('redirect' => array('baz', array(), 301)), array('baz', array(), 301)); - $redirect = new RedirectResponse('/example'); $data[] = array(array('redirect' => $redirect), $redirect); - $data[] = array(array('redirect_route' => new Url('test_route_b', array('key' => 'value'))), new Url('test_route_b', array('key' => 'value'), array('absolute' => TRUE))); + $data[] = array(array('redirect' => new Url('test_route_b', array('key' => 'value'))), new Url('test_route_b', array('key' => 'value'))); $data[] = array(array('programmed' => TRUE), NULL); $data[] = array(array('rebuild' => TRUE), NULL); $data[] = array(array('no_redirect' => TRUE), NULL); - $data[] = array(array('redirect' => FALSE), NULL); return $data; } diff --git a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php index 0bdc009f26a..e76e9a6f480 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php @@ -98,57 +98,34 @@ class FormSubmitterTest extends UnitTestCase { } /** - * Tests the redirectForm() method when a redirect is expected. + * Tests the redirectForm() method when the redirect is NULL. * * @covers ::redirectForm - * - * @dataProvider providerTestRedirectWithResult */ - public function testRedirectWithResult($redirect_value, $result, $status = 303) { + public function testRedirectWithNull() { $form_submitter = $this->getFormSubmitter(); $this->urlGenerator->expects($this->once()) ->method('generateFromPath') - ->will($this->returnValueMap(array( - array(NULL, array('query' => array(), 'absolute' => TRUE), ''), - array('foo', array('absolute' => TRUE), 'foo'), - array('bar', array('query' => array('foo' => 'baz'), 'absolute' => TRUE), 'bar'), - array('baz', array('absolute' => TRUE), 'baz'), - )) - ); + ->with(NULL, array('query' => array(), 'absolute' => TRUE)) + ->willReturn(''); $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface'); $form_state->expects($this->once()) ->method('getRedirect') - ->willReturn($redirect_value); + ->willReturn(NULL); $redirect = $form_submitter->redirectForm($form_state); - $this->assertSame($result, $redirect->getTargetUrl()); - $this->assertSame($status, $redirect->getStatusCode()); + $this->assertSame('', $redirect->getTargetUrl()); + $this->assertSame(303, $redirect->getStatusCode()); } /** - * Provides test data for testing the redirectForm() method with a redirect. - * - * @return array - * Returns some test data. - */ - public function providerTestRedirectWithResult() { - return array( - array(NULL, ''), - array('foo', 'foo'), - array(array('foo'), 'foo'), - array(array('bar', array('query' => array('foo' => 'baz'))), 'bar'), - array(array('baz', array(), 301), 'baz', 301), - ); - } - - /** - * Tests the redirectForm() with redirect_route when a redirect is expected. + * Tests redirectForm() when a redirect is a Url object. * * @covers ::redirectForm * - * @dataProvider providerTestRedirectWithRouteWithResult + * @dataProvider providerTestRedirectWithUrl */ - public function testRedirectWithRouteWithResult($redirect_value, $result, $status = 303) { + public function testRedirectWithUrl(Url $redirect_value, $result, $status = 303) { $container = new ContainerBuilder(); $container->set('url_generator', $this->urlGenerator); \Drupal::setContainer($container); @@ -176,7 +153,7 @@ class FormSubmitterTest extends UnitTestCase { * @return array * Returns some test data. */ - public function providerTestRedirectWithRouteWithResult() { + public function providerTestRedirectWithUrl() { return array( array(new Url('test_route_a', array(), array('absolute' => TRUE)), 'test-route'), array(new Url('test_route_b', array('key' => 'value'), array('absolute' => TRUE)), 'test-route/value'),