Skip to content

Commit

Permalink
More path utils
Browse files Browse the repository at this point in the history
  • Loading branch information
totten committed Dec 3, 2019
1 parent 3025964 commit 84f690c
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/PathUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

class PathUtil {

public static $SEP = DIRECTORY_SEPARATOR;

public static function getPwd() {
if (getenv('PWD')) {
// Symlink sensitivity training
Expand All @@ -29,4 +31,75 @@ public static function findCommand($name) {
return NULL;
}

/**
* Convert relative paths to absolute
*
* @param $expr
* @param string|NULL $base
* @return string
*/
public static function makeAbsolute($expr, $base = NULL) {
if (self::isAbsolute($expr)) {
return $expr;
}

if ($base === NULL) {
$base = self::getPwd();
}

$base = rtrim($base, '/' . self::$SEP);
return $base . self::$SEP . $expr;
}

public static function isAbsolute($expr) {
$slashes = '/' . self::$SEP;
if (strpos($slashes, $expr[0]) !== FALSE) {
return TRUE;
}
if (self::$SEP === '\\' && preg_match(';^[a-zA-Z]:[\\/];', $expr)) {
return TRUE;
}
return FALSE;
}

/**
* Evaluate as many expressions like "/./" or "/../" as we can.
*
* If the path is relative, then the leading "../" may not be evaluated.
*
* @param string $path
* @return string
*/
public static function evaluateDots($path) {
$q = preg_quote(self::$SEP, ';');

$path = self::cleanSlashes($path);
$hasTail = substr($path, -1) === self::$SEP ? self::$SEP : '';
if (!$hasTail) {
$path .= self::$SEP;
}

$path = preg_replace(";^(\.{$q})+(.);", '$2', $path);
while (preg_match(";{$q}\.\.?{$q};", $path)) {
$path = preg_replace(";{$q}\.{$q};", self::$SEP, $path);
$path = preg_replace(";{$q}[^{$q}]+{$q}\.\.{$q};", self::$SEP, $path);
}
return $hasTail ? $path : rtrim($path, self::$SEP);
}

/**
* @param $path
* @param $preferredSeparator
* @return array
*/
public static function cleanSlashes($path) {
if (self::$SEP !== '/') {
$path = str_replace('/', self::$SEP, $path);
}

$q = preg_quote(self::$SEP, ';');
$path = preg_replace(";{$q}+;", self::$SEP, $path);
return $path;
}

}
43 changes: 43 additions & 0 deletions tests/PathUtilTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
namespace Pogo;

use PHPUnit\Framework\TestCase;

class PathUtilTest extends TestCase {

public function getDotExamples() {
$exs = [
["/", "/unix/abs", "/unix/abs"],
["/", "unix/rel", "unix/rel"],
["/", "c:/win/abs", "c:/win/abs"],
["/", "win/rel", "win/rel"],
["/", "/c:/win/abs", "/c:/win/abs"],
["/", "/unix/foo/bar/..", "/unix/foo"],
["/", "/unix/foo/bar/../", "/unix/foo/"],
["/", "/unix/foo/bar/.", "/unix/foo/bar"],
["/", "/unix/foo/bar/./", "/unix/foo/bar/"],
["/", "/unix/foo/./bar", "/unix/foo/bar"],
["/", ".", "."],
["/", "../", "../"],
["/", "..", ".."],
["/", "./foo", "foo"],
["/", "../foo/bar", "../foo/bar"],
["/", ".foo", ".foo"],
];
return $exs;
}

/**
* @param string $sep
* @param string $inputPath
* @param string $expectPath
* @dataProvider getDotExamples
*/
public function testEvaluateDots($sep, $inputPath, $expectPath) {
$origSep = PathUtil::$SEP;
PathUtil::$SEP = $sep;
$this->assertEquals($expectPath, PathUtil::evaluateDots($inputPath));
PathUtil::$SEP = $origSep;
}

}

0 comments on commit 84f690c

Please sign in to comment.