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.
    }
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.
    }
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. }
Resolves a relative URL into a full URL from a base.

@since 140417 Initial release.

@param string $relative_url_uri_query_fragment A full URL; or a partial URI;
or only a query string, or only a fragment. Any of these can be parsed here.
@param string $base_url                        A base URL. Optional. Defaults to current location.
This defaults to the current URL. See: {@link current_url()}.

@throws \Exception If unable to parse `$relative_url_uri_query_fragment`.
@throws \Exception If there is no `$base`, and we're unable to detect current location.
@throws \Exception If unable to parse `$base` (or if `$base` has no host name).

@return string A full URL; else an exception will be thrown.
Resolves a relative URL into a full URL from a base .