/** * 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; }
/** * Get an entity instance and normalize the path * @param string $path * @return \sndsgd\fs\Dir|\sndsgd\fs\File */ public static function get($path) { $instance = new static($path); $instance->normalize(); return $instance; }