Example #1
0
 /**
  * Convert the link to a relative link by substracting a base URI
  *
  *  This is the opposite of resolving a relative link - i.e. creating a
  *  relative reference link from an original URI and a base URI.
  *
  *  If the two URIs do not intersect (e.g. the original URI is not in any
  *  way related to the base URI) the URI will not be modified.
  *
  * @param  Uri|string $baseUri
  * @return Uri
  */
 public function makeRelative($baseUri)
 {
     // Copy base URI, we should not modify it
     $baseUri = new static($baseUri);
     $this->normalize();
     $baseUri->normalize();
     $host = $this->getHost();
     $baseHost = $baseUri->getHost();
     if ($host && $baseHost && $host != $baseHost) {
         // Not the same hostname
         return $this;
     }
     $port = $this->getPort();
     $basePort = $baseUri->getPort();
     if ($port && $basePort && $port != $basePort) {
         // Not the same port
         return $this;
     }
     $scheme = $this->getScheme();
     $baseScheme = $baseUri->getScheme();
     if ($scheme && $baseScheme && $scheme != $baseScheme) {
         // Not the same scheme (e.g. HTTP vs. HTTPS)
         return $this;
     }
     // Remove host, port and scheme
     $this->setHost(null)->setPort(null)->setScheme(null);
     // Is path the same?
     if ($this->getPath() == $baseUri->getPath()) {
         $this->setPath('');
         return $this;
     }
     $pathParts = preg_split('|(/)|', $this->getPath(), null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
     $baseParts = preg_split('|(/)|', $baseUri->getPath(), null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
     // Get the intersection of existing path parts and those from the
     // provided URI
     $matchingParts = array_intersect_assoc($pathParts, $baseParts);
     // Loop through the matches
     foreach ($matchingParts as $index => $segment) {
         // If we skip an index at any point, we have parent traversal, and
         // need to prepend the path accordingly
         if ($index && !isset($matchingParts[$index - 1])) {
             array_unshift($pathParts, '../');
             continue;
         }
         // Otherwise, we simply unset the given path segment
         unset($pathParts[$index]);
     }
     // Reset the path by imploding path segments
     $this->setPath(implode($pathParts));
     return $this;
 }
Example #2
0
 /**
  * Transform References
  *
  * This function implements the "transform references" algorithm from
  * the RFC3986 specification for URIs.
  *
  * @see http://tools.ietf.org/html/rfc3986#page-31
  *
  * @param string $relative
  * @param bool   $strict
  *
  * @return static
  */
 public function transformReference($relative, $strict = false)
 {
     $base = $this;
     $relative = new static((string) $relative);
     $transformed = new static();
     if (!$strict && $relative->getScheme() == $this->getScheme()) {
         $relative->setScheme(null);
     }
     if ($relative->getScheme() !== null) {
         $transformed->setScheme($relative->getScheme());
         $transformed->setAuthority($relative->getAuthority());
         $transformed->setPath(static::remove_dot_segments($relative->getPath()));
         $transformed->setQuery($relative->getQuery());
     } else {
         if ($relative->getAuthority() !== null) {
             $transformed->setAuthority($relative->getAuthority());
             $transformed->setPath(static::remove_dot_segments($relative->getPath()));
             $transformed->setQuery($relative->getQuery());
         } else {
             if ($relative->getPath() == '') {
                 $transformed->setPath($base->getPath());
                 if ($relative->getQuery() !== null) {
                     $transformed->setQuery($relative->getQuery());
                 } else {
                     $transformed->setQuery($base->getQuery());
                 }
             } else {
                 if ('/' == substr($relative->getPath(), 0, 1)) {
                     $transformed->setPath(static::remove_dot_segments($relative->getPath()));
                 } else {
                     $transformed->setPath(static::merge($base->getPath(), $relative->getPath()));
                     $transformed->setPath(static::remove_dot_segments($transformed->getPath()));
                 }
                 $transformed->setQuery($relative->getQuery());
             }
             $transformed->setAuthority($base->getAuthority());
         }
         $transformed->setScheme($base->getScheme());
     }
     $transformed->setFragment($relative->getFragment());
     return $transformed;
 }