Skip to content

Commit bfda8a3

Browse files
committed
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 `/`.
2 parents 064ad62 + 6def8d1 commit bfda8a3

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,21 +302,28 @@ public function makePathRelative($endPath, $startPath)
302302
$startPath = strtr($startPath, '\\', '/');
303303
}
304304

305-
// Find for which character the the common path stops
306-
$offset = 0;
307-
while (isset($startPath[$offset]) && isset($endPath[$offset]) && $startPath[$offset] === $endPath[$offset]) {
308-
$offset++;
305+
// Split the paths into arrays
306+
$startPathArr = explode('/', trim($startPath, '/'));
307+
$endPathArr = explode('/', trim($endPath, '/'));
308+
309+
// Find for which directory the common path stops
310+
$index = 0;
311+
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
312+
$index++;
309313
}
310314

311315
// Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
312-
$diffPath = trim(substr($startPath, $offset), '/');
313-
$depth = strlen($diffPath) > 0 ? substr_count($diffPath, '/') + 1 : 0;
316+
$depth = count($startPathArr) - $index;
314317

315318
// Repeated "../" for each level need to reach the common path
316319
$traverser = str_repeat('../', $depth);
317320

321+
$endPathRemainder = implode('/', array_slice($endPathArr, $index));
322+
318323
// Construct $endPath from traversing to the common path, then to the remaining $endPath
319-
return $traverser.substr($endPath, $offset);
324+
$relativePath = $traverser . (strlen($endPathRemainder) > 0 ? $endPathRemainder . '/' : '');
325+
326+
return (strlen($relativePath) === 0) ? './' : $relativePath;
320327
}
321328

322329
/**

src/Symfony/Component/Filesystem/Tests/FilesystemTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,22 @@ public function providePathsForMakePathRelative()
733733
array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
734734
array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
735735
array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
736+
array('/aa/bb', '/aa/bb', './'),
737+
array('/aa/bb', '/aa/bb/', './'),
738+
array('/aa/bb/', '/aa/bb', './'),
739+
array('/aa/bb/', '/aa/bb/', './'),
740+
array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
741+
array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
742+
array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
743+
array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
744+
array('/aa/bb/cc', '/aa', 'bb/cc/'),
745+
array('/aa/bb/cc', '/aa/', 'bb/cc/'),
746+
array('/aa/bb/cc/', '/aa', 'bb/cc/'),
747+
array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
748+
array('/a/aab/bb', '/a/aa', '../aab/bb/'),
749+
array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
750+
array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
751+
array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
736752
);
737753

738754
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy