protected function resolveRelativeUrl($relative_url_uri_query_fragment, $base_url = '')
    {
        $relative_url_uri_query_fragment = (string) $relative_url_uri_query_fragment;
        $base_url                        = (string) $base_url;

        if (!$base_url) {
            $base_url = $this->currentUrl();
        } // Auto-detects current URL/location.

        $relative_parts         = $this->mustParseUrl($relative_url_uri_query_fragment, null, 0);
        $relative_parts['path'] = $this->nUrlPathSeps($relative_parts['path'], true);
        $base_parts             = $parts             = $this->mustParseUrl($base_url);

        if ($relative_parts['host']) {
            if (!$relative_parts['scheme']) {
                $relative_parts['scheme'] = $base_parts['scheme'];
            }
            return $this->mustUnparseUrl($relative_parts);
        }
        if (!$base_parts['host']) {
            throw new \Exception(sprintf('Unable to parse (missing base host name): `%1$s`.', $base_url));
        }
        if (isset($relative_parts['path'][0])) {
            if (mb_strpos($relative_parts['path'], '/') === 0) {
                $parts['path'] = ''; // Reduce to nothing if relative is absolute.
            } else {
                $parts['path'] = preg_replace('/\/[^\/]*$/u', '', $parts['path']).'/'; // Reduce to nearest `/`.
            }
            // Replace `/./` and `/foo/../` with `/` (resolve relatives).
            for ($_i = 1, $parts['path'] = $parts['path'].$relative_parts['path']; $_i > 0;) {
                $parts['path'] = preg_replace(['/\/\.\//u', '/\/(?!\.\.)[^\/]+\/\.\.\//u'], '/', $parts['path'], -1, $_i);
            } // unset($_i); // Just a little housekeeping.

            // We can ditch any unresolvable `../` patterns now.
            // For instance, if there were too many `../../../../../` back references.
            $parts['path'] = str_replace('../', '', $parts['path']);

            $parts['query'] = $relative_parts['query'];
            // Use relative query.
        } elseif (isset($relative_parts['query'][0])) {
            $parts['query'] = $relative_parts['query'];
        } // Relative query string supersedes base.

        $parts['fragment'] = $relative_parts['fragment']; // Always changes.

        return $this->mustUnparseUrl($parts); // Resolved now.
    }