jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/375931 )
Change subject: Move global functions into Wikimedia\RelPath class ...................................................................... Move global functions into Wikimedia\RelPath class Change-Id: I65a8d36a5e74b9614c1109c19b66f99c66c8809c --- M README.md M composer.json D src/RelPath.php A src/RelPath/RelPath.php A src/Wikimedia/RelPath.php M tests/RelPathTest.php 6 files changed, 224 insertions(+), 157 deletions(-) Approvals: Krinkle: Looks good to me, approved jenkins-bot: Verified diff --git a/README.md b/README.md index 421be52..0595c9c 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Here is how you use it: <pre lang="php"> -$relPath = RelPath\getRelativePath( '/srv/mediawiki/resources/src/startup.js', '/srv/mediawiki' ); +$relPath = \Wikimedia\RelPath::getRelativePath( '/srv/mediawiki/resources/src/startup.js', '/srv/mediawiki' ); // Result: string(24) "resources/src/startup.js" -$fullPath = RelPath\joinPath( '/srv/mediawiki', 'resources/src/startup.js' ); +$fullPath = \Wikimedia\RelPath::joinPath( '/srv/mediawiki', 'resources/src/startup.js' ); // Result: string(39) "/srv/mediawiki/resources/src/startup.js" </pre> diff --git a/composer.json b/composer.json index bbe8ff5..402ade4 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ ], "autoload": { "files": [ - "src/RelPath.php" + "src/RelPath/RelPath.php", + "src/Wikimedia/RelPath.php" ] }, "require": { diff --git a/src/RelPath.php b/src/RelPath.php deleted file mode 100644 index 86103c0..0000000 --- a/src/RelPath.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php -/** - * Copyright (c) 2015 Ori Livneh <o...@wikimedia.org> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * @file - * @author Ori Livneh <o...@wikimedia.org> - */ - -namespace RelPath; - -/** - * Split a path into path components. - * - * @param string $path File path. - * @return array Array of path components. - */ -function splitPath( $path ) { - $fragments = []; - - while ( true ) { - $cur = dirname( $path ); - if ( $cur[0] === DIRECTORY_SEPARATOR ) { - // dirname() on Windows sometimes returns a leading backslash, but other - // times retains the leading forward slash. Slashes other than the leading one - // are returned as-is, and therefore do not need to be touched. - // Furthermore, don't break on *nix where \ is allowed in file/directory names. - $cur[0] = '/'; - } - - if ( $cur === $path || ( $cur === '.' && basename( $path ) === $path ) ) { - break; - } - - $fragment = trim( substr( $path, strlen( $cur ) ), '/' ); - - if ( !$fragments ) { - $fragments[] = $fragment; - } elseif ( $fragment === '..' && basename( $cur ) !== '..' ) { - $cur = dirname( $cur ); - } elseif ( $fragment !== '.' ) { - $fragments[] = $fragment; - } - - $path = $cur; - } - - if ( $path !== '' ) { - $fragments[] = trim( $path, '/' ); - } - - return array_reverse( $fragments ); -} - -/** - * Return a relative filepath to path either from the current directory or from - * an optional start directory. Both paths must be absolute. - * - * @param string $path File path. - * @param string $start Start directory. Optional; if not specified, the current - * working directory will be used. - * @return string|bool Relative path, or false if input was invalid. - */ -function getRelativePath( $path, $start = null ) { - if ( $start === null ) { - // @codeCoverageIgnoreStart - $start = getcwd(); - } - // @codeCoverageIgnoreEnd - - if ( substr( $path, 0, 1 ) !== '/' || substr( $start, 0, 1 ) !== '/' ) { - return false; - } - - $pathParts = splitPath( $path ); - $countPathParts = count( $pathParts ); - - $startParts = splitPath( $start ); - $countStartParts = count( $startParts ); - - $commonLength = min( $countPathParts, $countStartParts ); - for ( $i = 0; $i < $commonLength; $i++ ) { - if ( $startParts[$i] !== $pathParts[$i] ) { - break; - } - } - - $relList = ( $countStartParts > $i ) - ? array_fill( 0, $countStartParts - $i, '..' ) - : []; - - $relList = array_merge( $relList, array_slice( $pathParts, $i ) ); - - return implode( '/', $relList ) ?: '.'; -} - -/** - * Join path components. - * - * @param string $base Base path. - * @param string $path File path to join to base path. - * @return string - */ -function joinPath( $base, $path ) { - if ( substr( $path, 0, 1 ) === '/' ) { - // $path is absolute. - return $path; - } - - if ( substr( $base, 0, 1 ) !== '/' ) { - // $base is relative. - return false; - } - - $pathParts = splitPath( $path ); - $resultParts = splitPath( $base ); - - while ( ( $part = array_shift( $pathParts ) ) !== null ) { - switch ( $part ) { - case '.': - break; - case '..': - if ( count( $resultParts ) > 1 ) { - array_pop( $resultParts ); - } - break; - default: - $resultParts[] = $part; - break; - } - } - - return implode( '/', $resultParts ); -} diff --git a/src/RelPath/RelPath.php b/src/RelPath/RelPath.php new file mode 100644 index 0000000..a09e9ca --- /dev/null +++ b/src/RelPath/RelPath.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright (c) 2015 Ori Livneh <o...@wikimedia.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @file + * @author Ori Livneh <o...@wikimedia.org> + */ + +namespace RelPath; + +use Wikimedia\RelPath; + +/** + * Split a path into path components. + * + * @param string $path File path. + * @return array Array of path components. + */ +function splitPath( $path ) { + return RelPath::splitPath( $path ); +} + +/** + * Return a relative filepath to path either from the current directory or from + * an optional start directory. Both paths must be absolute. + * + * @param string $path File path. + * @param string $start Start directory. Optional; if not specified, the current + * working directory will be used. + * @return string|bool Relative path, or false if input was invalid. + */ +function getRelativePath( $path, $start = null ) { + return RelPath::getRelativePath( $path, $start ); +} + +/** + * Join path components. + * + * @param string $base Base path. + * @param string $path File path to join to base path. + * @return string + */ +function joinPath( $base, $path ) { + return RelPath::oinPath( $base, $path ); +} diff --git a/src/Wikimedia/RelPath.php b/src/Wikimedia/RelPath.php new file mode 100644 index 0000000..aa8d16e --- /dev/null +++ b/src/Wikimedia/RelPath.php @@ -0,0 +1,154 @@ +<?php +/** + * Copyright (c) 2015 Ori Livneh <o...@wikimedia.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @file + * @author Ori Livneh <o...@wikimedia.org> + */ + +namespace Wikimedia; + +class RelPath { + /** + * Split a path into path components. + * + * @param string $path File path. + * @return array Array of path components. + */ + public static function splitPath( $path ) { + $fragments = []; + + while ( true ) { + $cur = dirname( $path ); + if ( $cur[0] === DIRECTORY_SEPARATOR ) { + // dirname() on Windows sometimes returns a leading backslash, but other + // times retains the leading forward slash. Slashes other than the leading one + // are returned as-is, and therefore do not need to be touched. + // Furthermore, don't break on *nix where \ is allowed in file/directory names. + $cur[0] = '/'; + } + + if ( $cur === $path || ( $cur === '.' && basename( $path ) === $path ) ) { + break; + } + + $fragment = trim( substr( $path, strlen( $cur ) ), '/' ); + + if ( !$fragments ) { + $fragments[] = $fragment; + } elseif ( $fragment === '..' && basename( $cur ) !== '..' ) { + $cur = dirname( $cur ); + } elseif ( $fragment !== '.' ) { + $fragments[] = $fragment; + } + + $path = $cur; + } + + if ( $path !== '' ) { + $fragments[] = trim( $path, '/' ); + } + + return array_reverse( $fragments ); + } + + /** + * Return a relative filepath to path either from the current directory or from + * an optional start directory. Both paths must be absolute. + * + * @param string $path File path. + * @param string $start Start directory. Optional; if not specified, the current + * working directory will be used. + * @return string|bool Relative path, or false if input was invalid. + */ + public static function getRelativePath( $path, $start = null ) { + if ( $start === null ) { + // @codeCoverageIgnoreStart + $start = getcwd(); + } + // @codeCoverageIgnoreEnd + + if ( substr( $path, 0, 1 ) !== '/' || substr( $start, 0, 1 ) !== '/' ) { + return false; + } + + $pathParts = self::splitPath( $path ); + $countPathParts = count( $pathParts ); + + $startParts = self::splitPath( $start ); + $countStartParts = count( $startParts ); + + $commonLength = min( $countPathParts, $countStartParts ); + for ( $i = 0; $i < $commonLength; $i++ ) { + if ( $startParts[$i] !== $pathParts[$i] ) { + break; + } + } + + $relList = ( $countStartParts > $i ) + ? array_fill( 0, $countStartParts - $i, '..' ) + : []; + + $relList = array_merge( $relList, array_slice( $pathParts, $i ) ); + + return implode( '/', $relList ) ?: '.'; + } + + /** + * Join path components. + * + * @param string $base Base path. + * @param string $path File path to join to base path. + * @return string + */ + public static function joinPath( $base, $path ) { + if ( substr( $path, 0, 1 ) === '/' ) { + // $path is absolute. + return $path; + } + + if ( substr( $base, 0, 1 ) !== '/' ) { + // $base is relative. + return false; + } + + $pathParts = self::splitPath( $path ); + $resultParts = self::splitPath( $base ); + + while ( ( $part = array_shift( $pathParts ) ) !== null ) { + switch ( $part ) { + case '.': + break; + case '..': + if ( count( $resultParts ) > 1 ) { + array_pop( $resultParts ); + } + break; + default: + $resultParts[] = $part; + break; + } + } + + return implode( '/', $resultParts ); + } +} diff --git a/tests/RelPathTest.php b/tests/RelPathTest.php index 7a418af..369f5df 100644 --- a/tests/RelPathTest.php +++ b/tests/RelPathTest.php @@ -83,13 +83,13 @@ * @dataProvider provideRelPathTestCases */ public function testRelPath( $path, $start, $expected ) { - $this->assertEquals( $expected, RelPath\getRelativePath( $path, $start ) ); + $this->assertEquals( $expected, \Wikimedia\RelPath::getRelativePath( $path, $start ) ); } /** * @dataProvider provideJoinPathTestCases */ public function testJoinPath( $base, $path, $expected ) { - $this->assertEquals( $expected, RelPath\joinPath( $base, $path ) ); + $this->assertEquals( $expected, \Wikimedia\RelPath::joinPath( $base, $path ) ); } } -- To view, visit https://gerrit.wikimedia.org/r/375931 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I65a8d36a5e74b9614c1109c19b66f99c66c8809c Gerrit-PatchSet: 5 Gerrit-Project: RelPath Gerrit-Branch: master Gerrit-Owner: Reedy <re...@wikimedia.org> Gerrit-Reviewer: Krinkle <krinklem...@gmail.com> Gerrit-Reviewer: Legoktm <lego...@member.fsf.org> Gerrit-Reviewer: Reedy <re...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits