Refactored Filesystem::makePathRelative function to correctly handle more use-cases

This commit is contained in:
Aharon Perkel 2012-07-11 01:22:37 +03:00
parent 064ad6255c
commit 6def8d1dd1
2 changed files with 30 additions and 7 deletions

View File

@ -302,21 +302,28 @@ class Filesystem
$startPath = strtr($startPath, '\\', '/');
}
// Find for which character the the common path stops
$offset = 0;
while (isset($startPath[$offset]) && isset($endPath[$offset]) && $startPath[$offset] === $endPath[$offset]) {
$offset++;
// Split the paths into arrays
$startPathArr = explode('/', trim($startPath, '/'));
$endPathArr = explode('/', trim($endPath, '/'));
// Find for which directory the common path stops
$index = 0;
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
$index++;
}
// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
$diffPath = trim(substr($startPath, $offset), '/');
$depth = strlen($diffPath) > 0 ? substr_count($diffPath, '/') + 1 : 0;
$depth = count($startPathArr) - $index;
// Repeated "../" for each level need to reach the common path
$traverser = str_repeat('../', $depth);
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
// Construct $endPath from traversing to the common path, then to the remaining $endPath
return $traverser.substr($endPath, $offset);
$relativePath = $traverser . (strlen($endPathRemainder) > 0 ? $endPathRemainder . '/' : '');
return (strlen($relativePath) === 0) ? './' : $relativePath;
}
/**

View File

@ -733,6 +733,22 @@ class FilesystemTest extends \PHPUnit_Framework_TestCase
array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
array('/aa/bb', '/aa/bb', './'),
array('/aa/bb', '/aa/bb/', './'),
array('/aa/bb/', '/aa/bb', './'),
array('/aa/bb/', '/aa/bb/', './'),
array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
array('/aa/bb/cc', '/aa', 'bb/cc/'),
array('/aa/bb/cc', '/aa/', 'bb/cc/'),
array('/aa/bb/cc/', '/aa', 'bb/cc/'),
array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
array('/a/aab/bb', '/a/aa', '../aab/bb/'),
array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
);
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {