<?php
/**
* Simple relative path normalizer utility.
*
* The utility was inspired by PHP's realPath function, though that required the given path to exist, RelativePath does not.
*
* Particularly useful is you need to parse and normalize paths gathered from for instance URL's and HTML pages.
*
* These functions are also included in Zip and ZipStream classes version 1.23 onwards on PHPClasses.org.
* http://www.phpclasses.org/package/6110 and http://www.phpclasses.org/package/6616 respectively.
*
* License: GNU LGPL, Attribution required for commercial implementations, requested for everything else.
*
* @author A. Grandt
* @copyright A. Grandt 2011
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @link http://www.phpclasses.org/package/6844
* @version 1.01
*/
class RelativePath {
const VERSION = 1.01;
/**
* Join $file to $dir path, and clean up any excess slashes.
*
* @param String $dir
* @param String $file
*/
public static function pathJoin($dir, $file) {
if (empty($dir) || empty($file)) {
return self::getRelativePath($dir . $file);
}
return self::getRelativePath($dir . '/' . $file);
}
/**
* Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments.
* If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off.
* The returned path will not end in a "/".
*
* @param String $relPath The path to clean up
* @return String the clean path
*/
public static function getRelativePath($path) {
$path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path));
$dirs = explode("/", rtrim(preg_replace('#^(\./)+#', '', $path), '/'));
$offset = 0;
$sub = 0;
$subOffset = 0;
$root = "";
if (empty($dirs[0])) {
$root = "/";
$dirs = array_splice($dirs, 1);
} else if (preg_match("#[A-Za-z]:#", $dirs[0])) {
$root = strtoupper($dirs[0]) . "/";
$dirs = array_splice($dirs, 1);
}
$newDirs = array();
foreach($dirs as $dir) {
if ($dir !== "..") {
$subOffset--;
$newDirs[++$offset] = $dir;
} else {
$subOffset++;
if (--$offset < 0) {
$offset = 0;
if ($subOffset > $sub) {
$sub++;
}
}
}
}
if (empty($root)) {
$root = str_repeat("../", $sub);
}
return $root . implode("/", array_slice($newDirs, 0, $offset));
}
}
?>