public function relativeTo($base, $schemaRelative = false)
    {
        if (false === ($base instanceof IRI)) {
            $base = new IRI($base);
        }
        $relative = clone $this;

        // Compare scheme
        if ($relative->scheme !== $base->scheme) {
            return $relative;
        }

        // Compare authority
        if ($relative->getAuthority() !== $base->getAuthority()) {
            if (true === $schemaRelative) {
                $relative->scheme = null;
            }

            return $relative;
        }
        $relative->scheme = null;
        $relative->host = null;
        $relative->userinfo = null;
        $relative->port = null;

        // Compare path
        $baseSegments     = explode('/', $base->path);
        $relativeSegments = explode('/', $relative->path);
        $len = min(count($baseSegments), count($relativeSegments)) - 1;  // do not move beyond last segment

        $pos = 0;

        while (($baseSegments[$pos] === $relativeSegments[$pos]) && ($pos < $len)) {
            $pos++;
        }

        $relative->path = '';
        $numBaseSegments = count($baseSegments) - $pos - 1;
        if ($numBaseSegments > 0) {
            $relative->path .= str_repeat('../', $numBaseSegments);
        }

        if (($baseSegments[$pos] !== $relativeSegments[$pos]) ||
            ((null === $relative->query) && (null === $relative->fragment)) ||
            ($base->path === '')) {
            // if the two paths differ or if there's neither a query component nor a fragment
            // or there is no base path, we need to consider this IRI's path

            if (($relative->path === '') && (false !== strpos($relativeSegments[$pos], ':'))) {
                // if the first path segment contains a colon, we need to
                // prepend a ./ to distinguish it from an absolute IRI
                $relative->path .= './';
            }

            $relative->path .= implode('/', array_slice($relativeSegments, $pos));

            // .. and ensure that the resulting path isn't empty
            if (($relative->path === '')) {
                $relative->path .= './';
            }
        }

        if ($relative->query !== $base->query) {
            return $relative;
        }

        if (null !== $relative->fragment) {
            $relative->query = null;
        }

        return $relative;
    }
public function relativeTo($base, $schemaRelative = false)
    {
        if (false === ($base instanceof IRI)) {
            $base = new IRI($base);
        }
        $relative = clone $this;

        // Compare scheme
        if ($relative->scheme !== $base->scheme) {
            return $relative;
        }

        // Compare authority
        if ($relative->getAuthority() !== $base->getAuthority()) {
            if (true === $schemaRelative) {
                $relative->scheme = null;
            }

            return $relative;
        }
        $relative->scheme = null;
        $relative->host = null;
        $relative->userinfo = null;
        $relative->port = null;

        // Compare path
        $baseSegments     = explode('/', $base->path);
        $relativeSegments = explode('/', $relative->path);
        $len = min(count($baseSegments), count($relativeSegments)) - 1;  // do not move beyond last segment

        $pos = 0;

        while (($baseSegments[$pos] === $relativeSegments[$pos]) && ($pos < $len)) {
            $pos++;
        }

        $relative->path = '';
        $numBaseSegments = count($baseSegments) - $pos - 1;
        if ($numBaseSegments > 0) {
            $relative->path .= str_repeat('../', $numBaseSegments);
        }

        if (($baseSegments[$pos] !== $relativeSegments[$pos]) ||
            ((null === $relative->query) && (null === $relative->fragment)) ||
            ($base->path === '')) {
            // if the two paths differ or if there's neither a query component nor a fragment
            // or there is no base path, we need to consider this IRI's path

            if (($relative->path === '') && (false !== strpos($relativeSegments[$pos], ':'))) {
                // if the first path segment contains a colon, we need to
                // prepend a ./ to distinguish it from an absolute IRI
                $relative->path .= './';
            }

            $relative->path .= implode('/', array_slice($relativeSegments, $pos));

            // .. and ensure that the resulting path isn't empty
            if (($relative->path === '')) {
                $relative->path .= './';
            }
        }

        if ($relative->query !== $base->query) {
            return $relative;
        }

        if (null !== $relative->fragment) {
            $relative->query = null;
        }

        return $relative;
    }
public function relativeTo ( $ base , $ schemaRelative = false ) { if ( false === ( $ base instanceof IRI ) ) { $ base = new IRI ( $ base ) ; } $ relative = clone $ this ; // Compare scheme if ( $ relative -> scheme !== $ base -> scheme ) { return $ relative ; } // Compare authority if ( $ relative -> getAuthority ( ) !== $ base -> getAuthority ( ) ) { if ( true === $ schemaRelative ) { $ relative -> scheme = null ; } return $ relative ; } $ relative -> scheme = null ; $ relative -> host = null ; $ relative -> userinfo = null ; $ relative -> port = null ; // Compare path $ baseSegments = explode ( '/' , $ base -> path ) ; $ relativeSegments = explode ( '/' , $ relative -> path ) ; $ len = min ( count ( $ baseSegments ) , count ( $ relativeSegments ) ) - 1 ; // do not move beyond last segment $ pos = 0 ; while ( ( $ baseSegments [ $ pos ] === $ relativeSegments [ $ pos ] ) && ( $ pos < $ len ) ) { $ pos ++ ; } $ relative -> path = '' ; $ numBaseSegments = count ( $ baseSegments ) - $ pos - 1 ; if ( $ numBaseSegments > 0 ) { $ relative -> path .= str_repeat ( '../' , $ numBaseSegments ) ; } if ( ( $ baseSegments [ $ pos ] !== $ relativeSegments [ $ pos ] ) || ( ( null === $ relative -> query ) && ( null === $ relative -> fragment ) ) || ( $ base -> path === '' ) ) { // if the two paths differ or if there's neither a query component nor a fragment // or there is no base path, we need to consider this IRI's path if ( ( $ relative -> path === '' ) && ( false !== strpos ( $ relativeSegments [ $ pos ] , ':' ) ) ) { // if the first path segment contains a colon, we need to // prepend a ./ to distinguish it from an absolute IRI $ relative -> path .= './' ; } $ relative -> path .= implode ( '/' , array_slice ( $ relativeSegments , $ pos ) ) ; // .. and ensure that the resulting path isn't empty if ( ( $ relative -> path === '' ) ) { $ relative -> path .= './' ; } } if ( $ relative -> query !== $ base -> query ) { return $ relative ; } if ( null !== $ relative -> fragment ) { $ relative -> query = null ; } return $ relative ; }
Transform this IRI to a IRI reference relative to the passed base IRI

@param IRI|string $base The (relative) IRI reference that should be
be used as base IRI.
@param bool             Defines whether schema-relative IRIs such
as `//example.com` should be created (`true`)
or not (`false`).

@return IRI The IRI reference relative to the passed base IRI.

@throws \InvalidArgumentException If an invalid IRI is passed.

@api
Transform this IRI to a IRI reference relative to the passed base IRI