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:
- { name: event_subscriber }
arguments: ['@language_manager']
scope: request
redirect_response_subscriber:
class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber
arguments: ['@url_generator']
tags:
- { name: event_subscriber }
scope: request
request_close_subscriber:
class: Drupal\Core\EventSubscriber\RequestCloseSubscriber
tags:
......
......@@ -15,7 +15,8 @@
*/
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.
......@@ -34,7 +35,7 @@ function _batch_page() {
$batch = Drupal::service('batch.storage')->load($_REQUEST['id']);
if (!$batch) {
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() {
if ($_batch['progressive']) {
// Revert the 'destination' that was saved in batch_process().
if (isset($_batch['destination'])) {
$_GET['destination'] = $_batch['destination'];
Drupal::request()->query->set('destination', $_batch['destination']);
}
// Determine the target path to redirect to.
......@@ -426,7 +427,10 @@ function _batch_finished() {
}
// 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
// form needs to be rebuilt, save the final $form_state for
......@@ -438,6 +442,14 @@ function _batch_finished() {
if (function_exists($function)) {
$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 = '') {
}
/**
* 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.
* 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 = '') {
* not available, the current path.
*
* @see current_path()
* @see drupal_goto()
*/
function drupal_get_destination() {
$destination = &drupal_static(__FUNCTION__);
......@@ -570,7 +569,6 @@ function drupal_get_destination() {
* - 'fragment': The fragment of $url, if existent.
*
* @see url()
* @see drupal_goto()
* @ingroup php_wrappers
*/
function drupal_parse_url($url) {
......@@ -629,84 +627,6 @@ function drupal_encode_path($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.
*
......
This diff is collapsed.
......@@ -626,7 +626,14 @@ function install_run_task($task, &$install_state) {
}
// Process the batch. For progressive batches, this will redirect.
// 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
// any output from the batch process, until the task is complete.
......
......@@ -830,7 +830,7 @@ function update_do_one($module, $number, $dependency_map, &$context) {
*
* @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
// affect visiting users.
$maintenance_mode = config('system.maintenance')->get('enabled');
......@@ -883,7 +883,7 @@ function update_batch($start, $redirect = NULL, $url = NULL, $batch = array(), $
'file' => 'core/includes/update.inc',
);
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);
$path = $destination['path'];
$options['query'] = $destination['query'];
$options['fragment'] = $destination['fragment'];
// The 'Location' HTTP header must always be absolute.
$options['absolute'] = TRUE;
$response->setTargetUrl($this->urlGenerator->generateFromPath($path, $options));
}
}
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = array('checkRedirectUrl');
return $events;
}
}
......@@ -10,6 +10,11 @@
use Drupal\Core\Annotation\Action;
use Drupal\Core\Annotation\Translation;
use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Routing\PathBasedGeneratorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Redirects to a different URL.
......@@ -22,11 +27,60 @@
*/
class GotoAction extends ConfigurableActionBase {
/**
* The event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $dispatcher;
/**
* The url generator service.
*
* @var \Drupal\Core\Routing\PathBasedGeneratorInterface
*/
protected $urlGenerator;
/**
* Constructs a new DeleteNode object.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin ID for the plugin instance.
* @param array $plugin_definition
* The plugin implementation definition.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* The tempstore factory.
* @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
* The url generator service.
*/
public function __construct(array $configuration, $plugin_id, array $plugin_definition, EventDispatcherInterface $dispatcher, PathBasedGeneratorInterface $url_generator) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->dispatcher = $dispatcher;
$this->urlGenerator = $url_generator;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('event_dispatcher'), $container->get('url_generator'));
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
drupal_goto($this->configuration['url']);
$url = $this->urlGenerator
->generateFromPath($this->configuration['url'], array('absolute' => TRUE));
$response = new RedirectResponse($url);
$listener = function($event) use ($response) {
$event->setResponse($response);
};
// Add the listener to the event dispatcher.
$this->dispatcher->addListener(KernelEvents::RESPONSE, $listener);
}
/**
......
<?php
use Drupal\Component\Utility\Crypt;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Implements hook_menu().
......@@ -70,5 +71,5 @@ function aggregator_test_feed($use_last_modified = FALSE, $use_etag = FALSE) {
* Page callback that redirects to another feed.
*/
function aggregator_test_redirect() {
drupal_goto('aggregator/test-feed', array(), 301);
return new RedirectResponse(url('aggregator/test-feed', array('absolute' => TRUE)), 301);
}
......@@ -6,6 +6,7 @@
*/
use Drupal\comment\Plugin\Core\Entity\Comment;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
......@@ -238,7 +239,7 @@ function comment_multiple_delete_confirm($form, &$form_state) {
if (!$comment_counter) {
drupal_set_message(t('There do not appear to be any comments to delete, or your selected comment was deleted by another administrator.'));
drupal_goto('admin/content/comment');
return new RedirectResponse(url('admin/content/comment', array('absolute' => TRUE)));
}
else {
return confirm_form($form,
......
......@@ -7,6 +7,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\comment\Plugin\Core\Entity\Comment;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
/**
......@@ -47,7 +48,7 @@ function comment_reply(EntityInterface $node, $pid = NULL) {
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
}
else {
......@@ -62,19 +63,19 @@ function comment_reply(EntityInterface $node, $pid = NULL) {
if ($comment->nid->target_id != $node->nid) {
// Attempting to reply to a comment not belonging to the current nid.
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
// Display the parent comment
$build['comment_parent'] = comment_view($comment);
}
else {
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
}
else {
drupal_set_message(t('You are not authorized to view comments.'), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
}
// This is the case where the comment is in response to a node. Display the node.
......@@ -85,14 +86,14 @@ function comment_reply(EntityInterface $node, $pid = NULL) {
// Should we show the reply box?
if ($node->comment != COMMENT_NODE_OPEN) {
drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
elseif (user_access('post comments')) {
$build['comment_form'] = comment_add($node, $pid);
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
drupal_goto("node/$node->nid");
return new RedirectResponse(url("node/$node->nid", array('absolute' => TRUE)));
}
}
......@@ -120,5 +121,5 @@ function comment_approve(Comment $comment) {
$comment->save();
drupal_set_message(t('Comment approved.'));
drupal_goto('node/' . $comment->nid->target_id);
return new RedirectResponse('node/' . $comment->nid->target_id, array('absolute' => TRUE));
}
......@@ -5,6 +5,8 @@
* Administration pages for image settings.
*/
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Menu callback; Listing of all current image styles.
*/
......@@ -284,7 +286,7 @@ function image_effect_form($form, &$form_state, $style, $effect) {
// If there's no configuration for this image effect, return to
// the image style page.
if (!isset($effect['form callback'])) {
drupal_goto('admin/config/media/image-styles/manage/' . $style->id());
return new RedirectResponse(url('admin/config/media/image-styles/manage/' . $style->id(), array('absolute' => TRUE)));
}
$form_state['image_style'] = $style;
$form_state['image_effect'] = $effect;
......
......@@ -7,6 +7,7 @@
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
......@@ -298,7 +299,7 @@ function language_admin_delete_form($form, &$form_state, $language) {
if (language_default()->langcode == $langcode) {
drupal_set_message(t('The default language cannot be deleted.'));
drupal_goto('admin/config/regional/language');
return new RedirectResponse(url('admin/config/regional/language', array('absolute' => TRUE)));
}
// For other languages, warn the user that data loss is ahead.
......
......@@ -8,6 +8,7 @@
use Drupal\Core\Language\Language;
use Drupal\locale\SourceString;
use Drupal\locale\TranslationString;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
......@@ -479,9 +480,9 @@ function locale_translation_manual_status() {
// Execute a batch if required. A batch is only used when remote files
// are checked.
if (batch_get()) {
batch_process('admin/reports/translations');
return batch_process('admin/reports/translations');
}
drupal_goto('admin/reports/translations');
return new RedirectResponse(url('admin/reports/translations', array('absolute' => TRUE)));
}
/**
......
......@@ -12,6 +12,7 @@
use Drupal\Core\Entity\EntityManager;
use Drupal\Component\Utility\String;
use Drupal\user\TempStoreFactory;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -97,7 +98,7 @@ public function getConfirmText() {
public function buildForm(array $form, array &$form_state) {
$this->nodes = $this->tempStoreFactory->get('node_multiple_delete_confirm')->get($GLOBALS['user']->uid);
if (empty($this->nodes)) {
drupal_goto($this->getCancelPath());
return new RedirectResponse(url($this->getCancelPath(), array('absolute' => TRUE)));
}
$form['nodes'] = array(
......
......@@ -10,6 +10,7 @@
*/
use Drupal\Core\Entity\EntityInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Page callback: Displays add content links for available content types.
......@@ -34,7 +35,7 @@ function node_add_page() {
// Bypass the node/add listing if only one content type is available.
if (count($content) == 1) {
$type = array_shift($content);
drupal_goto('node/add/' . $type->type);
return new RedirectResponse(url('node/add/' . $type->type, array('absolute' => TRUE)));
}
return array('#theme' => 'node_add_list', '#content' => $content);
}
......
......@@ -8,6 +8,7 @@
namespace Drupal\overlay\EventSubscriber;
use Drupal\Core\ContentNegotiation;
use Drupal\Core\Routing\PathBasedGeneratorInterface;
use Drupal\user\UserData;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
......@@ -34,6 +35,13 @@ class OverlaySubscriber implements EventSubscriberInterface {
*/
protected $userData;
/**
* The url generator service.
*
* @var \Drupal\Core\Routing\PathBasedGeneratorInterface
*/
protected $urlGenerator;
/**
* Constructs an OverlaySubscriber object.
*
......@@ -41,10 +49,13 @@ class OverlaySubscriber implements EventSubscriberInterface {
* The content negotiation service.
* @param \Drupal\user\UserData $user_data
* The user.data service.
* @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
* The url generator service.
*/
public function __construct(ContentNegotiation $negotiation, UserData $user_data) {
public function __construct(ContentNegotiation $negotiation, UserData $user_data, PathBasedGeneratorInterface $url_generator) {
$this->negotiation = $negotiation;
$this->userData = $user_data;
$this->urlGenerator = $url_generator;
}
/**
......@@ -75,7 +86,12 @@ public function onRequest(GetResponseEvent $event) {
// <front>#overlay=admin/modules to actually enable the overlay.
if (isset($_SESSION['overlay_enable_redirect']) && $_SESSION['overlay_enable_redirect']) {
unset($_SESSION['overlay_enable_redirect']);
$response = new RedirectResponse(url('<front>', array('fragment' => 'overlay=' . $current_path, 'absolute' => TRUE)));
$url = $this->urlGenerator
->generateFromPath('<front>', array(
'fragment' => 'overlay=' . $current_path,
'absolute' => TRUE,
));
$response = new RedirectResponse($url);
$event->setResponse($response);
}
......@@ -134,6 +150,32 @@ public function onResponse(FilterResponseEvent $event) {
}
}
}
$response = $event->getResponse();
if ($response instanceOf RedirectResponse) {
$path = $response->getTargetUrl();
// The authorize.php script bootstraps Drupal to a very low level, where
// the PHP code that is necessary to close the overlay properly will not
// be loaded. Therefore, if we are redirecting to authorize.php inside
// the overlay, instead redirect back to the current page with
// instructions to close the overlay there before redirecting to the
// final destination.
$options = array('absolute' => TRUE);
if ($path == system_authorized_get_url($options) || $path == system_authorized_batch_processing_url($options)) {
$_SESSION['overlay_close_dialog'] = array($path, $options);
$path = current_path();
$options = drupal_get_query_parameters();
}
// If the current page request is inside the overlay, add ?render=overlay
// to the new path, so that it appears correctly inside the overlay.
if (isset($options['query'])) {
$options['query'] += array('render' => 'overlay');
}
else {
$options['query'] = array('render' => 'overlay');
}
$response->setTargetUrl($this->urlGenerator->generateFromPath($path, $options));
}
}
}
......
......@@ -5,6 +5,7 @@
* Displays the Drupal administration interface in an overlay.
*/
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Drupal\block\Plugin\Core\Entity\Block;
......@@ -176,34 +177,6 @@ function overlay_library_info() {
return $libraries;
}
/**
* Implements hook_drupal_goto_alter().
*/
function overlay_drupal_goto_alter(&$path, &$options, &$http_response_code) {
if (overlay_get_mode() == 'child') {
// The authorize.php script bootstraps Drupal to a very low level, where
// the PHP code that is necessary to close the overlay properly will not be
// loaded. Therefore, if we are redirecting to authorize.php inside the
// overlay, instead redirect back to the current page with instructions to
// close the overlay there before redirecting to the final destination; see
// overlay_init().
if ($path == system_authorized_get_url() || $path == system_authorized_batch_processing_url()) {
$_SESSION['overlay_close_dialog'] = array($path, $options);
$path = current_path();
$options = drupal_get_query_parameters();
}
// If the current page request is inside the overlay, add ?render=overlay
// to the new path, so that it appears correctly inside the overlay.
if (isset($options['query'])) {
$options['query'] += array('render' => 'overlay');
}
else {
$options['query'] = array('render' => 'overlay');
}
}
}
/**
* Implements hook_batch_alter().
*
......@@ -293,7 +266,7 @@ function overlay_user_dismiss_message() {
Drupal::service('user.data')->set('overlay', $user->uid, 'message_dismissed', 1);
drupal_set_message(t('The message has been dismissed. You can change your overlay settings at any time by visiting your profile page.'));
// Destination is normally given. Go to the user profile as a fallback.
drupal_goto('user/' . $user->uid . '/edit');
return new RedirectResponse(url('user/' . $user->uid . '/edit', array('absolute' => TRUE)));
}
/**
......
......@@ -3,4 +3,4 @@ services:
class: Drupal\overlay\EventSubscriber\OverlaySubscriber
tags:
- { name: event_subscriber }
arguments: ['@content_negotiation', '@user.data']
arguments: ['@content_negotiation', '@user.data', '@url_generator']
......@@ -6,6 +6,7 @@
*/
use Drupal\Core\Language\Language;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Page callback: Presents the search form and/or search results.
......@@ -41,7 +42,7 @@ function search_view($module = NULL, $keys = '') {
if ($keys) {
$path .= '/' . $keys;