/** * Combine the URL with another URL and return a new URL instance. * * Follows the rules specific in RFC 3986 section 5.4. * * @param string $url Relative URL to combine with * * @return Url * @throws \InvalidArgumentException * @link http://tools.ietf.org/html/rfc3986#section-5.4 */ public function combine($url) { $url = static::fromString($url); // Use the more absolute URL as the base URL if (!$this->isAbsolute() && $url->isAbsolute()) { $url = $url->combine($this); } $parts = $url->getParts(); // Passing a URL with a scheme overrides everything if ($parts['scheme']) { return clone $url; } // Setting a host overrides the entire rest of the URL if ($parts['host']) { return new static($this->scheme, $parts['host'], $parts['user'], $parts['pass'], $parts['port'], $parts['path'], $parts['query'] instanceof Query ? clone $parts['query'] : $parts['query'], $parts['fragment']); } if (!$parts['path'] && $parts['path'] !== '0') { // The relative URL has no path, so check if it is just a query $path = $this->path ?: ''; $query = $parts['query'] ?: $this->query; } else { $query = $parts['query']; if ($parts['path'][0] == '/' || !$this->path) { // Overwrite the existing path if the rel path starts with "/" $path = $parts['path']; } else { // If the relative URL does not have a path or the base URL // path does not end in a "/" then overwrite the existing path // up to the last "/" $path = substr($this->path, 0, strrpos($this->path, '/') + 1) . $parts['path']; } } $result = new self($this->scheme, $this->host, $this->username, $this->password, $this->port, $path, $query instanceof Query ? clone $query : $query, $parts['fragment']); if ($path) { $result->removeDotSegments(); } return $result; }