Skip to content

Instantly share code, notes, and snippets.

@silassare
Last active October 27, 2017 13:16
Show Gist options
  • Save silassare/e048711c92ca9de0eca77e8e6d08a004 to your computer and use it in GitHub Desktop.
Save silassare/e048711c92ca9de0eca77e8e6d08a004 to your computer and use it in GitHub Desktop.
A simple php class that resolve relative path to absolute path according to a given root path.
<?php
/**
* Usage:
*
* <?php
* include 'OPathResolver.php';
*
* $root = '/var/www/html/';
* $path = '../../log/';
* $abs_path = OPathResolver::resolve($root, $path);
* echo $abs_path; // /var/log
*/
class OPathResolver {
const DS = DIRECTORY_SEPARATOR;
/**
* resolve a given path according to a given root
*
* @param string $root the root path
* @param string $path the path to resolve
*
* @return string the absolute path
*/
public static function resolve( $root, $path ) {
$root = self::normalize( $root );
$path = self::normalize( $path );
if ( self::isRelative( $path ) ) {
if ( ( self::DS === '/' AND $path[ 0 ] === '/' ) OR preg_match( "#^[\w]+:#", $path ) ) {
// path start form the root
// linux - unix -> /
// windows -> D:
$full_path = $path;
} else {
$full_path = $root . self::DS . $path;
}
$path = preg_replace( '#^(https?):[/]([^/])#', '$1://$2', self::job( $full_path ) );
}
return $path;
}
/**
* where the resolve job is done
*
* @param string $path the path to normalize
*
* @return string the resolved path
*/
private static function job( $path ) {
$in = explode( self::DS, $path );
$out = array();
// preserve linux root first char '/' like in: /root/path/to/
if ( $path[ 0 ] === self::DS ) {
array_push( $out, '' );
}
foreach ( $in as $part ) {
// ignore part that have no value
if ( empty( $part ) OR $part === '.' )
continue;
if ( $part !== '..' ) {
// cool we found a new part
array_push( $out, $part );
} else if ( count( $out ) > 0 ) {
// going back up? sure
array_pop( $out );
} else {
// now here we don't like
throw new Exception( sprintf( "climbing above root is dangerous: %s", $path ) );
}
}
if ( !count( $out ) ) {
return self::DS;
}
if ( count( $out ) === 1 ) {
array_push( $out, null );
}
return join( self::DS, $out );
}
/**
* normalize a given path according to OS specific directory separator
*
* @param string $path the path to normalize
*
* @return string the normalized path
*/
public static function normalize( $path ) {
if ( self::DS == '\\' )
return strtr( $path, '/', '\\' );
return strtr( $path, '\\', '/' );
}
/**
* check if a given path is relative or not
*
* @param string $path the path
*
* @return bool true if it is a relative path, false otherwise
*/
public static function isRelative( $path ) {
return preg_match( "#^\.{1,2}[/\\\\]?#", $path )
OR preg_match( "#[/\\\\]\.{1,2}[/\\\\]#", $path )
OR preg_match( "#[/\\\\]\.{1,2}$#", $path )
OR preg_match( "#^[a-zA-Z0-9_.][^:]*$#", $path );
}
}
@silassare
Copy link
Author

Usage:

 <?php
   include 'OPathResolver.php';

   $root = '/var/www/html/';
   $path = '../../log/';
   $abs_path = OPathResolver::resolve($root, $path);
   echo $abs_path;

Output:

/var/log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment