mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API CHANGE HTTP::setGetVar() always returns absolute URLs. Use Director::makeRelative() to make them relative again.
API CHANGE HTTP::setGetVar() combines any GET parameters in PHP array notation (e.g. "foo[bar]=val") instead of replacing the whole array BUGFIX HTTP::setGetVar() uses parse_url() and http_build_query() to add query parameters to an existing URL, instead of doing its own regex-based parsing. This means existing GET parameters are correctly url encoded. git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@98373 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
ff724b44de
commit
792b4cc1c4
@ -73,26 +73,59 @@ class HTTP {
|
|||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will try to include a GET parameter for an existing URL,
|
||||||
|
* preserving existing parameters and fragments.
|
||||||
|
* If no URL is given, falls back to $_SERVER['REQUEST_URI'].
|
||||||
|
*
|
||||||
|
* CAUTION: If the URL is determined to be relative,
|
||||||
|
* it is prepended with Director::absoluteBaseURL().
|
||||||
|
* This method will always return an absolute URL because
|
||||||
|
* Director::makeRelative() can lead to inconsistent results.
|
||||||
|
*
|
||||||
|
* @param String $varname
|
||||||
|
* @param String $varvalue
|
||||||
|
* @param String $currentURL Relative or absolute URL (Optional).
|
||||||
|
* @return String Absolute URL
|
||||||
|
*/
|
||||||
public static function setGetVar($varname, $varvalue, $currentURL = null) {
|
public static function setGetVar($varname, $varvalue, $currentURL = null) {
|
||||||
$scriptbase = $currentURL ? $currentURL : $_SERVER['REQUEST_URI'];
|
$uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
$scriptbase = str_replace('&', '&', $scriptbase);
|
// We need absolute URLs for parse_url()
|
||||||
$scriptbase = preg_replace('/\?' . quotemeta($varname) . '=([^&]*)&/', '?', $scriptbase);
|
if(Director::is_relative_url($uri)) $uri = Director::absoluteBaseURL() . $uri;
|
||||||
$scriptbase = preg_replace('/([\?&]+)' . quotemeta($varname) . '=([^&]*)/', null, $scriptbase);
|
|
||||||
|
|
||||||
$suffix = '';
|
// try to parse uri
|
||||||
if(($hashPos = strpos($scriptbase,'#')) !== false) {
|
$parts = parse_url($uri);
|
||||||
$suffix .= substr($scriptbase, $hashPos);
|
if(!$parts) {
|
||||||
$scriptbase = substr($scriptbase, 0, $hashPos);
|
throw new InvalidArgumentException("Can't parse URL: " . $uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($varvalue !== null) {
|
// Parse params and add new variable
|
||||||
$scriptbase .= (strrpos($scriptbase,'?') !== false) ? '&' : '?';
|
$params = array();
|
||||||
$scriptbase .= "$varname=" . (isset($urlEncodeVarValue) ? urlencode($varvalue) : $varvalue);
|
if(isset($parts['query'])) parse_str($parts['query'], $params);
|
||||||
}
|
$params[$varname] = $varvalue;
|
||||||
|
|
||||||
$scriptbase = str_replace('&','&',$scriptbase);
|
// Recompile Uri
|
||||||
return $scriptbase . $suffix;
|
$newUri = $parts['scheme'] . '://' . (
|
||||||
|
isset($parts['user']) && $parts['user'] != '' && isset($parts['pass'])
|
||||||
|
? $parts['user'] . ':' . $parts['pass'] . '@'
|
||||||
|
: ''
|
||||||
|
) .
|
||||||
|
$parts['host'] . (
|
||||||
|
isset($parts['path']) && $parts['path'] != ''
|
||||||
|
? $parts['path']
|
||||||
|
: ''
|
||||||
|
) . (
|
||||||
|
($params)
|
||||||
|
? '?' . http_build_query($params)
|
||||||
|
: ''
|
||||||
|
) . (
|
||||||
|
isset($parts['fragment']) && $parts['fragment'] != ''
|
||||||
|
? '#' . $parts['fragment']
|
||||||
|
: ''
|
||||||
|
);
|
||||||
|
|
||||||
|
return $newUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function RAW_setGetVar($varname, $varvalue, $currentURL = null) {
|
static function RAW_setGetVar($varname, $varvalue, $currentURL = null) {
|
||||||
|
@ -47,19 +47,51 @@ class HTTPTest extends SapphireTest {
|
|||||||
* Tests {@link HTTP::setGetVar()}
|
* Tests {@link HTTP::setGetVar()}
|
||||||
*/
|
*/
|
||||||
public function testSetGetVar() {
|
public function testSetGetVar() {
|
||||||
$expected = array (
|
// HACK No easy way to get the current URL without the query string or fragment
|
||||||
'/?foo=bar' => array('foo', 'bar', '/'),
|
$base = Director::absoluteBaseURL() . 'dev/tests/HTTPTest';
|
||||||
'/?baz=buz&foo=bar' => array('foo', 'bar', '/?baz=buz'),
|
|
||||||
'/?buz=baz&foo=baz' => array('foo', 'baz', '/?foo=bar&buz=baz'),
|
$this->assertEquals(
|
||||||
'/?foo=var' => array('foo', 'var', '/?foo=&foo=bar'),
|
$base . '?foo=bar',
|
||||||
'/?foo[test]=var' => array('foo[test]', 'var', '/?foo[test]=another')
|
HTTP::setGetVar('foo', 'bar'),
|
||||||
|
'Omitting a URL falls back to current URL'
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach($expected as $result => $args) {
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
call_user_func_array(array('HTTP', 'setGetVar'), $args), str_replace('&', '&', $result)
|
Director::absoluteBaseURL() . 'relative/url?foo=bar',
|
||||||
|
HTTP::setGetVar('foo', 'bar', 'relative/url'),
|
||||||
|
'Relative URL without slash prefix returns URL with absolute base'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
Director::absoluteBaseURL() . '/relative/url?foo=bar',
|
||||||
|
HTTP::setGetVar('foo', 'bar', '/relative/url'),
|
||||||
|
'Relative URL with slash prefix returns URL with absolute base'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
Director::absoluteBaseURL() . '/relative/url?baz=buz&foo=bar',
|
||||||
|
HTTP::setGetVar('foo', 'bar', '/relative/url?baz=buz'),
|
||||||
|
'Relative URL with existing query params, and new added key'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'http://test.com/?foo=new&buz=baz',
|
||||||
|
HTTP::setGetVar('foo', 'new', 'http://test.com/?foo=old&buz=baz'),
|
||||||
|
'Absolute URL without path and multipe existing query params, overwriting an existing parameter'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'http://test.com/?foo=new',
|
||||||
|
HTTP::setGetVar('foo', 'new', 'http://test.com/?foo=&foo=old'),
|
||||||
|
'Absolute URL and empty query param'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
// http_build_query() escapes angular brackets, they should be correctly urldecoded by the browser client
|
||||||
|
'http://test.com/?foo%5Btest%5D=one&foo%5Btest%5D=two',
|
||||||
|
HTTP::setGetVar('foo[test]', 'two', 'http://test.com/?foo[test]=one'),
|
||||||
|
'Absolute URL and PHP array query string notation'
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user