merged branch aharonp/master (PR #4842)
Commits
-------
6def8d1
Refactored Filesystem::makePathRelative function to correctly handle more use-cases
Discussion
----------
Refactored the makePathRelative function
The function was failing in a number of different use cases because the function was incorrectly using a character offset comparison to determine where the common path stops.
I've fixed this by splitting up the paths into their individual directories and then comparing the directory names.
If the paths match then the function will return `./` and not an empty string. This is for consistency sake, to ensure all returned paths end with `/`.
This commit is contained in:
commit
bfda8a3c29
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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')) {
|
||||
|
Reference in New Issue
Block a user