/**
  * Allow the setting of a URL
  *
  * This is here so that RootURLController can change the URL of the request
  * without us loosing all the other info attached (like headers)
  *
  * @param string $url The new URL
  * @return HTTPRequest The updated request
  */
 public function setUrl($url)
 {
     $this->url = $url;
     // Normalize URL if its relative (strictly speaking), or has leading slashes
     if (Director::is_relative_url($url) || preg_match('/^\\//', $url)) {
         $this->url = preg_replace(array('/\\/+/', '/^\\//', '/\\/$/'), array('/', '', ''), $this->url);
     }
     if (preg_match('/^(.*)\\.([A-Za-z][A-Za-z0-9]*)$/', $this->url, $matches)) {
         $this->url = $matches[1];
         $this->extension = $matches[2];
     }
     if ($this->url) {
         $this->dirParts = preg_split('|/+|', $this->url);
     } else {
         $this->dirParts = array();
     }
     return $this;
 }
 /**
  * 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']. Uses parse_url() to
  * dissect the URL, and http_build_query() to reconstruct it with the additional parameter.
  * Converts any '&' (ampersand) URL parameter separators to the more XHTML compliant '&'.
  *
  * 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.
  * @param string $separator Separator for http_build_query().
  *
  * @return string
  */
 public static function setGetVar($varname, $varvalue, $currentURL = null, $separator = '&')
 {
     $uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']);
     $isRelative = false;
     // We need absolute URLs for parse_url()
     if (Director::is_relative_url($uri)) {
         $uri = Director::absoluteBaseURL() . $uri;
         $isRelative = true;
     }
     // try to parse uri
     $parts = parse_url($uri);
     if (!$parts) {
         throw new InvalidArgumentException("Can't parse URL: " . $uri);
     }
     // Parse params and add new variable
     $params = array();
     if (isset($parts['query'])) {
         parse_str($parts['query'], $params);
     }
     $params[$varname] = $varvalue;
     // Generate URI segments and formatting
     $scheme = isset($parts['scheme']) ? $parts['scheme'] : 'http';
     $user = isset($parts['user']) && $parts['user'] != '' ? $parts['user'] : '';
     if ($user != '') {
         // format in either user:pass@host.com or user@host.com
         $user .= isset($parts['pass']) && $parts['pass'] != '' ? ':' . $parts['pass'] . '@' : '@';
     }
     $host = isset($parts['host']) ? $parts['host'] : '';
     $port = isset($parts['port']) && $parts['port'] != '' ? ':' . $parts['port'] : '';
     $path = isset($parts['path']) && $parts['path'] != '' ? $parts['path'] : '';
     // handle URL params which are existing / new
     $params = $params ? '?' . http_build_query($params, null, $separator) : '';
     // keep fragments (anchors) intact.
     $fragment = isset($parts['fragment']) && $parts['fragment'] != '' ? '#' . $parts['fragment'] : '';
     // Recompile URI segments
     $newUri = $scheme . '://' . $user . $host . $port . $path . $params . $fragment;
     if ($isRelative) {
         return Director::makeRelative($newUri);
     }
     return $newUri;
 }
 public function testIsRelativeUrl()
 {
     $siteUrl = Director::absoluteBaseURL();
     $this->assertFalse(Director::is_relative_url('http://test.com'));
     $this->assertFalse(Director::is_relative_url('https://test.com'));
     $this->assertFalse(Director::is_relative_url('   https://test.com/testpage   '));
     $this->assertTrue(Director::is_relative_url('test.com/testpage'));
     $this->assertFalse(Director::is_relative_url('ftp://test.com'));
     $this->assertTrue(Director::is_relative_url('/relative'));
     $this->assertTrue(Director::is_relative_url('relative'));
     $this->assertTrue(Director::is_relative_url('/relative/?url=http://test.com'));
     $this->assertTrue(Director::is_relative_url('/relative/#=http://test.com'));
 }