Commit 00cb147e authored by catch's avatar catch

Issue #1668866 by ParisLiakos, aspilicious, tim.plunkett, pdrake, g.oechsler,...

Issue #1668866 by ParisLiakos, aspilicious, tim.plunkett, pdrake, g.oechsler, dawehner, Berdir, corvus_ch, damiankloip, disasm, marcingy, neclimdul: Replace drupal_goto() with RedirectResponse.
parent 660f2d0d
...@@ -365,6 +365,12 @@ services: ...@@ -365,6 +365,12 @@ services:
- { name: event_subscriber } - { name: event_subscriber }
arguments: ['@language_manager'] arguments: ['@language_manager']
scope: request scope: request
redirect_response_subscriber:
class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber
arguments: ['@url_generator']
tags:
- { name: event_subscriber }
scope: request
request_close_subscriber: request_close_subscriber:
class: Drupal\Core\EventSubscriber\RequestCloseSubscriber class: Drupal\Core\EventSubscriber\RequestCloseSubscriber
tags: tags:
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
*/ */
use Drupal\Core\Batch\Percentage; use Drupal\Core\Batch\Percentage;
use \Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
/** /**
* Renders the batch processing page based on the current state of the batch. * Renders the batch processing page based on the current state of the batch.
...@@ -34,7 +35,7 @@ function _batch_page() { ...@@ -34,7 +35,7 @@ function _batch_page() {
$batch = Drupal::service('batch.storage')->load($_REQUEST['id']); $batch = Drupal::service('batch.storage')->load($_REQUEST['id']);
if (!$batch) { if (!$batch) {
drupal_set_message(t('No active batch.'), 'error'); drupal_set_message(t('No active batch.'), 'error');
drupal_goto(); return new RedirectResponse(url('<front>', array('absolute' => TRUE)));
} }
} }
...@@ -412,7 +413,7 @@ function _batch_finished() { ...@@ -412,7 +413,7 @@ function _batch_finished() {
if ($_batch['progressive']) { if ($_batch['progressive']) {
// Revert the 'destination' that was saved in batch_process(). // Revert the 'destination' that was saved in batch_process().
if (isset($_batch['destination'])) { if (isset($_batch['destination'])) {
$_GET['destination'] = $_batch['destination']; Drupal::request()->query->set('destination', $_batch['destination']);
} }
// Determine the target path to redirect to. // Determine the target path to redirect to.
...@@ -426,7 +427,10 @@ function _batch_finished() { ...@@ -426,7 +427,10 @@ function _batch_finished() {
} }
// Use drupal_redirect_form() to handle the redirection logic. // Use drupal_redirect_form() to handle the redirection logic.
drupal_redirect_form($_batch['form_state']); $redirect = drupal_redirect_form($_batch['form_state']);
if (is_object($redirect)) {
return $redirect;
}
// If no redirection happened, redirect to the originating page. In case the // If no redirection happened, redirect to the originating page. In case the
// form needs to be rebuilt, save the final $form_state for // form needs to be rebuilt, save the final $form_state for
...@@ -438,6 +442,14 @@ function _batch_finished() { ...@@ -438,6 +442,14 @@ function _batch_finished() {
if (function_exists($function)) { if (function_exists($function)) {
$function($_batch['source_url'], array('query' => array('op' => 'finish', 'id' => $_batch['id']))); $function($_batch['source_url'], array('query' => array('op' => 'finish', 'id' => $_batch['id'])));
} }
elseif ($function === NULL) {
// Default to RedirectResponse objects when nothing specified.
$url = url($_batch['source_url'], array(
'absolute' => TRUE,
'query' => array('op' => 'finish', 'id' => $_batch['id']),
));
return new RedirectResponse($url);
}
} }
} }
......
...@@ -503,7 +503,7 @@ function drupal_http_build_query(array $query, $parent = '') { ...@@ -503,7 +503,7 @@ function drupal_http_build_query(array $query, $parent = '') {
} }
/** /**
* Prepares a 'destination' URL query parameter for use with drupal_goto(). * Prepares a 'destination' URL query parameter for use with url().
* *
* Used to direct the user back to the referring page after completing a form. * Used to direct the user back to the referring page after completing a form.
* By default the current URL is returned. If a destination exists in the * By default the current URL is returned. If a destination exists in the
...@@ -516,7 +516,6 @@ function drupal_http_build_query(array $query, $parent = '') { ...@@ -516,7 +516,6 @@ function drupal_http_build_query(array $query, $parent = '') {
* not available, the current path. * not available, the current path.
* *
* @see current_path() * @see current_path()
* @see drupal_goto()
*/ */
function drupal_get_destination() { function drupal_get_destination() {
$destination = &drupal_static(__FUNCTION__); $destination = &drupal_static(__FUNCTION__);
...@@ -570,7 +569,6 @@ function drupal_get_destination() { ...@@ -570,7 +569,6 @@ function drupal_get_destination() {
* - 'fragment': The fragment of $url, if existent. * - 'fragment': The fragment of $url, if existent.
* *
* @see url() * @see url()
* @see drupal_goto()
* @ingroup php_wrappers * @ingroup php_wrappers
*/ */
function drupal_parse_url($url) { function drupal_parse_url($url) {
...@@ -629,84 +627,6 @@ function drupal_encode_path($path) { ...@@ -629,84 +627,6 @@ function drupal_encode_path($path) {
return str_replace('%2F', '/', rawurlencode($path)); return str_replace('%2F', '/', rawurlencode($path));
} }
/**
* Sends the user to a different Drupal page.
*
* This issues an on-site HTTP redirect. The function makes sure the redirected
* URL is formatted correctly.
*
* If a destination was specified in the current request's URI (i.e.,
* $_GET['destination']) then it will override the $path and $options values
* passed to this function. This provides the flexibility to build a link to
* user/login and override the default redirection so that the user is
* redirected to a specific path after logging in:
* @code
* $query = array('destination' => "node/$node->nid");
* $link = l(t('Log in'), 'user/login', array('query' => $query));
* @endcode
*
* Drupal will ensure that messages set by drupal_set_message() and other
* session data are written to the database before the user is redirected.
*
* This function ends the request; use it instead of a return in your menu
* callback.
*
* @param $path
* (optional) A Drupal path or a full URL, which will be passed to url() to
* compute the redirect for the URL.
* @param $options
* (optional) An associative array of additional URL options to pass to url().
* @param $http_response_code
* (optional) The HTTP status code to use for the redirection, defaults to
* 302. The valid values for 3xx redirection status codes are defined in
* @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3 RFC 2616 @endlink
* and the
* @link http://tools.ietf.org/html/draft-reschke-http-status-308-07 draft for the new HTTP status codes: @endlink
* - 301: Moved Permanently (the recommended value for most redirects).
* - 302: Found (default in Drupal and PHP, sometimes used for spamming search
* engines).
* - 303: See Other.
* - 304: Not Modified.
* - 305: Use Proxy.
* - 307: Temporary Redirect.
*
* @see drupal_get_destination()
* @see url()
*/
function drupal_goto($path = '', array $options = array(), $http_response_code = 302) {
// A destination in $_GET always overrides the function arguments.
// We do not allow absolute URLs to be passed via $_GET, as this can be an
// attack vector, with the following exception:
// - Absolute URLs that point to this site (i.e. same base URL and
// base path) are allowed.
if (isset($_GET['destination']) && (!url_is_external($_GET['destination']) || _external_url_is_local($_GET['destination']))) {
$destination = drupal_parse_url($_GET['destination']);
$path = $destination['path'];
$options['query'] = $destination['query'];
$options['fragment'] = $destination['fragment'];
}
drupal_alter('drupal_goto', $path, $options, $http_response_code);
// The 'Location' HTTP header must be absolute.
$options['absolute'] = TRUE;
$url = Drupal::urlGenerator()->generateFromPath($path, $options);
if (drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) {
drupal_session_commit();
}
$response = new RedirectResponse($url, $http_response_code);
// @todo We should not send the response here: http://drupal.org/node/1668866
$response->sendHeaders();
// The "Location" header sends a redirect status code to the HTTP daemon. In
// some cases this can be wrong, so we make sure none of the code below the
// drupal_goto() call gets executed upon redirection.
exit;
}
/** /**
* Determines if an external URL points to this Drupal installation. * Determines if an external URL points to this Drupal installation.
* *
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
use Drupal\Core\Template\Attribute; use Drupal\Core\Template\Attribute;
use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Utility\Color; use Drupal\Core\Utility\Color;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
/** /**
* @defgroup forms Form builder functions * @defgroup forms Form builder functions
...@@ -227,9 +231,8 @@ function drupal_get_form($form_arg) { ...@@ -227,9 +231,8 @@ function drupal_get_form($form_arg) {
* errors. * errors.
* - redirect: Used to redirect the form on submission. It may either be a * - redirect: Used to redirect the form on submission. It may either be a
* string containing the destination URL, or an array of arguments * string containing the destination URL, or an array of arguments
* compatible with drupal_goto(). See drupal_redirect_form() for complete * compatible with url(). See url() for complete information.
* information. * - no_redirect: If set to TRUE the form will NOT perform a redirect,
* - no_redirect: If set to TRUE the form will NOT perform a drupal_goto(),
* even if 'redirect' is set. * even if 'redirect' is set.
* - method: The HTTP form method to use for finding the input for this form. * - method: The HTTP form method to use for finding the input for this form.
* May be 'post' or 'get'. Defaults to 'post'. Note that 'get' method * May be 'post' or 'get'. Defaults to 'post'. Note that 'get' method
...@@ -413,7 +416,12 @@ function drupal_build_form($form_id, &$form_state) { ...@@ -413,7 +416,12 @@ function drupal_build_form($form_id, &$form_state) {
// appropriate information persists to the next page request. // appropriate information persists to the next page request.
// All of the handlers in the pipeline receive $form_state by reference and // All of the handlers in the pipeline receive $form_state by reference and
// can use it to know or update information about the state of the form. // can use it to know or update information about the state of the form.
drupal_process_form($form_id, $form, $form_state); $response = drupal_process_form($form_id, $form, $form_state);
// If the form returns some kind of response, deliver it.
if ($response instanceof Response) {
_drupal_form_send_response($response);
}
// If this was a successful submission of a single-step form or the last step // If this was a successful submission of a single-step form or the last step
// of a multi-step form, then drupal_process_form() issued a redirect to // of a multi-step form, then drupal_process_form() issued a redirect to
...@@ -858,6 +866,10 @@ function drupal_retrieve_form($form_id, &$form_state) { ...@@ -858,6 +866,10 @@ function drupal_retrieve_form($form_id, &$form_state) {
// If $callback was returned by a hook_forms() implementation, call it. // If $callback was returned by a hook_forms() implementation, call it.
// Otherwise, call the function named after the form id. // Otherwise, call the function named after the form id.
$form = call_user_func_array($callback, $args); $form = call_user_func_array($callback, $args);
// If the form returns some kind of response, deliver it.
if ($form instanceof Response) {
_drupal_form_send_response($form);
}
$form['#form_id'] = $form_id; $form['#form_id'] = $form_id;
return $form; return $form;
...@@ -941,7 +953,10 @@ function drupal_process_form($form_id, &$form, &$form_state) { ...@@ -941,7 +953,10 @@ function drupal_process_form($form_id, &$form, &$form_state) {
} }
$batch['progressive'] = !$form_state['programmed']; $batch['progressive'] = !$form_state['programmed'];
batch_process(); $response = batch_process();
if ($batch['progressive']) {
return $response;
}
// Execution continues only for programmatic forms. // Execution continues only for programmatic forms.
// For 'regular' forms, we get redirected to the batch processing // For 'regular' forms, we get redirected to the batch processing
...@@ -953,7 +968,10 @@ function drupal_process_form($form_id, &$form, &$form_state) { ...@@ -953,7 +968,10 @@ function drupal_process_form($form_id, &$form, &$form_state) {
$form_state['executed'] = TRUE; $form_state['executed'] = TRUE;
// Redirect the form based on values in $form_state. // Redirect the form based on values in $form_state.
drupal_redirect_form($form_state); $redirect = drupal_redirect_form($form_state);
if (is_object($redirect)) {
return $redirect;
}
} }
// Don't rebuild or cache form submissions invoked via drupal_form_submit(). // Don't rebuild or cache form submissions invoked via drupal_form_submit().
...@@ -1245,10 +1263,10 @@ function drupal_validate_form($form_id, &$form, &$form_state) { ...@@ -1245,10 +1263,10 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
* *
* Usually (for exceptions, see below) $form_state['redirect'] determines where * 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 * to redirect the user. This can be set either to a string (the path to
* redirect to), or an array of arguments for drupal_goto(). If * redirect to), or an array of arguments for url(). If $form_state['redirect']
* $form_state['redirect'] is missing, the user is usually (again, see below for * is missing, the user is usually (again, see below for exceptions) redirected
* exceptions) redirected back to the page they came from, where they should see * back to the page they came from, where they should see a fresh, unpopulated
* a fresh, unpopulated copy of the form. * copy of the form.
* *
* 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 'node':
* @code * @code
...@@ -1279,12 +1297,11 @@ function drupal_validate_form($form_id, &$form, &$form_state) { ...@@ -1279,12 +1297,11 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
* form builder functions or form validation/submit handlers. * form builder functions or form validation/submit handlers.
* - If $form_state['redirect'] is set to FALSE, redirection is disabled. * - If $form_state['redirect'] is set to FALSE, redirection is disabled.
* - If none of the above conditions has prevented redirection, then the * - If none of the above conditions has prevented redirection, then the
* redirect is accomplished by calling drupal_goto(), passing in the value of * redirect is accomplished by returning a RedirectResponse, passing in the
* $form_state['redirect'] if it is set, or the current path if it is * value of $form_state['redirect'] if it is set, or the current path if it is
* not. drupal_goto() preferentially uses the value of $_GET['destination'] * not. RedirectResponse preferentially uses the value of $_GET['destination']
* (the 'destination' URL query string) if it is present, so this will * (the 'destination' URL query string) if it is present, so this will
* override any values set by $form_state['redirect']. Note that during * override any values set by $form_state['redirect'].
* installation, install_goto() is called in place of drupal_goto().
* *
* @param $form_state * @param $form_state
* An associative array containing the current state of the form. * An associative array containing the current state of the form.
...@@ -1305,22 +1322,33 @@ function drupal_redirect_form($form_state) { ...@@ -1305,22 +1322,33 @@ function drupal_redirect_form($form_state) {
if (!empty($form_state['no_redirect'])) { if (!empty($form_state['no_redirect'])) {
return; return;
} }
// Only invoke drupal_goto() if redirect value was not set to FALSE. // Only invoke a redirection if redirect value was not set to FALSE.
if (!isset($form_state['redirect']) || $form_state['redirect'] !== FALSE) { if (!isset($form_state['redirect']) || $form_state['redirect'] !== FALSE) {
if (isset($form_state['redirect'])) { if (isset($form_state['redirect'])) {
if (is_array($form_state['redirect'])) { if (is_array($form_state['redirect'])) {
call_user_func_array('drupal_goto', $form_state['redirect']); $options = isset($form_state['redirect'][1]) ? $form_state['redirect'][1] : array();
// Redirections should always use absolute URLs.
$options['absolute'] = TRUE;
$status_code = isset($form_state['redirect'][2]) ? $form_state['redirect'][2] : 302;
return new RedirectResponse(url($form_state['redirect'][0], $options), $status_code);
} }
else { else {
// This function can be called from the installer, which guarantees // This function can be called from the installer, which guarantees
// that $redirect will always be a string, so catch that case here // that $redirect will always be a string, so catch that case here
// and use the appropriate redirect function. // and use the appropriate redirect function.
$function = drupal_installation_attempted() ? 'install_goto' : 'drupal_goto'; if (drupal_installation_attempted()) {
$function($form_state['redirect']); install_goto($form_state['redirect']);
}
else {
return new RedirectResponse(url($form_state['redirect'], array('absolute' => TRUE)));
}
} }
} }
$request = Drupal::request(); $url = url(Drupal::request()->attributes->get('system_path'), array(
drupal_goto($request->attributes->get('system_path'), array('query' => $request->query->all())); 'query' => Drupal::request()->query->all(),
'absolute' => TRUE,
));
return new RedirectResponse($url);
} }
} }
...@@ -4845,6 +4873,28 @@ function _form_set_attributes(&$element, $class = array()) { ...@@ -4845,6 +4873,28 @@ function _form_set_attributes(&$element, $class = array()) {
} }
} }
/**
* Triggers kernel.response and sends a form response.
*
* @deprecated This function is to be used internally by Form API only.
*
* @param \Symfony\Component\HttpFoundation\Response $response
* A response object.
*/
function _drupal_form_send_response(Response $response) {
$request = Drupal::request();
$kernel = Drupal::service('http_kernel');
$event = new FilterResponseEvent($kernel, $request, $kernel::MASTER_REQUEST, $response);
Drupal::service('event_dispatcher')->dispatch(KernelEvents::RESPONSE, $event);
// Prepare and send the response.
$event->getResponse()
->prepare($request)
->send();
$kernel->terminate($request, $response);
exit;
}
/** /**
* @} End of "defgroup form_api". * @} End of "defgroup form_api".
*/ */
...@@ -5067,9 +5117,6 @@ function batch_set($batch_definition) { ...@@ -5067,9 +5117,6 @@ function batch_set($batch_definition) {
/** /**
* Processes the batch. * Processes the batch.
* *
* Unless the batch has been marked with 'progressive' = FALSE, the function
* issues a drupal_goto and thus ends page execution.
*
* This function is generally not needed in form submit handlers; * This function is generally not needed in form submit handlers;
* Form API takes care of batches that were set during form submission. * Form API takes care of batches that were set during form submission.
* *
...@@ -5080,11 +5127,12 @@ function batch_set($batch_definition) { ...@@ -5080,11 +5127,12 @@ function batch_set($batch_definition) {
* URL of the batch processing page. * URL of the batch processing page.
* @param $redirect_callback * @param $redirect_callback
* (optional) Specify a function to be called to redirect to the progressive * (optional) Specify a function to be called to redirect to the progressive
* processing page. By default drupal_goto() will be used to redirect to a * processing page.
* page which will do the progressive page. Specifying another function will *
* allow the progressive processing to be processed differently. * @return \Symfony\Component\HttpFoundation\RedirectResponse|null
* A redirect response if the batch is progressive. No return value otherwise.
*/ */
function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'drupal_goto') { function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = NULL) {
$batch =& batch_get(); $batch =& batch_get();
drupal_theme_initialize(); drupal_theme_initialize();
...@@ -5124,11 +5172,12 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'd ...@@ -5124,11 +5172,12 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'd
// the generic error message. // the generic error message.
$batch['error_message'] = t('Please continue to <a href="@error_url">the error page</a>', array('@error_url' => url($url, array('query' => array('id' => $batch['id'], 'op' => 'finished'))))); $batch['error_message'] = t('Please continue to <a href="@error_url">the error page</a>', array('@error_url' => url($url, array('query' => array('id' => $batch['id'], 'op' => 'finished')))));
// Clear the way for the drupal_goto() redirection to the batch processing // Clear the way for the redirection to the batch processing page, by
// page, by saving and unsetting the 'destination', if there is any. // saving and unsetting the 'destination', if there is any.
if (isset($_GET['destination'])) { $request = Drupal::request();
$batch['destination'] = $_GET['destination']; if ($request->query->has('destination')) {
unset($_GET['destination']); $batch['destination'] = $request->query->get('destination');
$request->query->remove('destination');
} }
// Store the batch. // Store the batch.
...@@ -5138,8 +5187,14 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'd ...@@ -5138,8 +5187,14 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = 'd
$_SESSION['batches'][$batch['id']] = TRUE; $_SESSION['batches'][$batch['id']] = TRUE;
// Redirect for processing. // Redirect for processing.
$function = $batch['redirect_callback']; $options = array('query' => array('op' => 'start', 'id' => $batch['id']));
$function($batch['url'], array('query' => array('op' => 'start', 'id' => $batch['id']))); if (($function = $batch['redirect_callback']) && function_exists($function)) {
$function($batch['url'], $options);
}
else {
$options['absolute'] = TRUE;
return new RedirectResponse(url($batch['url'], $options));
}
} }
else { else {
// Non-progressive execution: bypass the whole progressbar workflow // Non-progressive execution: bypass the whole progressbar workflow
......
...@@ -626,7 +626,14 @@ function install_run_task($task, &$install_state) { ...@@ -626,7 +626,14 @@ function install_run_task($task, &$install_state) {
} }
// Process the batch. For progressive batches, this will redirect. // Process the batch. For progressive batches, this will redirect.
// Otherwise, the batch will complete. // Otherwise, the batch will complete.
batch_process(install_redirect_url($install_state), install_full_redirect_url($install_state)); $response = batch_process(install_redirect_url($install_state), install_full_redirect_url($install_state));
if ($response instanceof Response) {
// Save $_SESSION data from batch.
drupal_session_commit();
// Send the response.
$response->send();
exit;
}
} }
// If we are in the middle of processing this batch, keep sending back // If we are in the middle of processing this batch, keep sending back
// any output from the batch process, until the task is complete. // any output from the batch process, until the task is complete.
......
...@@ -830,7 +830,7 @@ function update_do_one($module, $number, $dependency_map, &$context) { ...@@ -830,7 +830,7 @@ function update_do_one($module, $number, $dependency_map, &$context) {
* *
* @see update_resolve_dependencies() * @see update_resolve_dependencies()
*/ */
function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $redirect_callback = 'drupal_goto') { function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $redirect_callback = NULL) {
// During the update, bring the site offline so that schema changes do not // During the update, bring the site offline so that schema changes do not
// affect visiting users. // affect visiting users.
$maintenance_mode = config('system.maintenance')->get('enabled'); $maintenance_mode = config('system.maintenance')->get('enabled');
...@@ -883,7 +883,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $ ...@@ -883,7 +883,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $
'file' => 'core/includes/update.inc', 'file' => 'core/includes/update.inc',
); );
batch_set($batch); batch_set($batch);
batch_process($redirect, $url, $redirect_callback); return batch_process($redirect, $url, $redirect_callback);
} }
/** /**
......
<?php
/**
* @file
* Contains \Drupal\Core\EventSubscriber\RedirectResponseSubscriber.
*/
namespace Drupal\Core\EventSubscriber;
use Drupal\Core\Routing\PathBasedGeneratorInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Access subscriber for controller requests.
*/
class RedirectResponseSubscriber implements EventSubscriberInterface {
/**
* The url generator service.
*
* @var \Drupal\Core\Routing\PathBasedGeneratorInterface
*/
protected $urlGenerator;
/**
* Constructs a RedirectResponseSubscriber object.
*
* @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
* The url generator service.
*/
public function __construct(PathBasedGeneratorInterface $url_generator) {
$this->urlGenerator = $url_generator;
}
/**
* Allows manipulation of the response object when performing a redirect.
*
* @param Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The Event to process.
*/
public function checkRedirectUrl(FilterResponseEvent $event) {
$response = $event->getResponse();
if ($response instanceOf RedirectResponse) {
$options = array();
$redirect_path = $response->getTargetUrl();
$destination = $event->getRequest()->query->get('destination');
// A destination in $_GET always overrides the current RedirectResponse.
// We do not allow absolute URLs to be passed via $_GET, as this can be an
// attack vector, with the following exception:
// - Absolute URLs that point to this site (i.e. same base URL and
// base path) are allowed.
if ($destination && (!url_is_external($destination) || _external_url_is_local($destination))) {
$destination = drupal_parse_url($destination);