merged branch Crell/redirect-set-target (PR #5081)

Commits
-------

76815fe Allow the targetUrl on a redirect response to be set explicilty.

Discussion
----------

Allow the targetUrl on a redirect response to be set explicilty.

Currently, RedirectResponse gets a Url set only when it's created, in the constructor.  There is no way to change it later.  That's a problem, because then you cannot change that Url from, say, a Kernel.response event listener.  That's a use case that Drupal in particular needs, because on redirects we allow modules to change the redirect target.  We also allow for redirect overrides via a GET parameter.

This PR refactors RedirectResponse to allow for a setTargetUrl() method.  It gets called from the constructor now, and can also be called from wherever.  It does not deal with changing the status code, just the Url (and by implication the content body).

Hopefully I got the coding style right this time... :-)

---------------------------------------------------------------------------

by vicb at 2012-07-27T15:45:47Z

> Currently, RedirectResponse gets a Url set only when it's created, in the constructor. There is no way to change it later. That's a problem, because then you cannot change that Url from, say, a Kernel.response event listener.

You can not change the target URL, but you can create a new `RedirectResponse` to override the original one (by calling `$event->setResponse()` in the listener).
This commit is contained in:
Fabien Potencier 2012-07-28 08:21:01 +02:00
commit 21d7b63ee8
2 changed files with 44 additions and 17 deletions

View File

@ -39,24 +39,9 @@ class RedirectResponse extends Response
throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
}
$this->targetUrl = $url;
parent::__construct('', $status, $headers);
parent::__construct(
sprintf('<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="refresh" content="1;url=%1$s" />
<title>Redirecting to %1$s</title>
</head>
<body>
Redirecting to <a href="%1$s">%1$s</a>.
</body>
</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8')),
$status,
array_merge($headers, array('Location' => $url))
);
$this->setTargetUrl($url);
if (!$this->isRedirect()) {
throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status));
@ -80,4 +65,38 @@ class RedirectResponse extends Response
{
return $this->targetUrl;
}
/**
* Sets the redirect target of this response.
*
* @param string $url The URL to redirect to
*
* @return RedirectResponse The current response.
*/
public function setTargetUrl($url)
{
if (empty($url)) {
throw new \InvalidArgumentException('Cannot redirect to an empty URL.');
}
$this->targetUrl = $url;
$this->setContent(
sprintf('<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="refresh" content="1;url=%1$s" />
<title>Redirecting to %1$s</title>
</head>
<body>
Redirecting to <a href="%1$s">%1$s</a>.
</body>
</html>', htmlspecialchars($url, ENT_QUOTES, 'UTF-8')));
$this->headers->set('Location', $url);
return $this;
}
}

View File

@ -40,6 +40,14 @@ class RedirectResponseTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo.bar', $response->getTargetUrl());
}
public function testSetTargetUrl()
{
$response = new RedirectResponse('foo.bar');
$response->setTargetUrl('baz.beep');
$this->assertEquals('baz.beep', $response->getTargetUrl());
}
public function testCreate()
{
$response = RedirectResponse::create('foo', 301);