-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
... to help validate paths provided via a ruleset property before using them in sniffs. The utility method in this class will also convert the paths from relative paths to absolute paths. The resulting array will have the original relative path as the key and the final absolute path as the value to allow for lookups. Includes dedicated unit tests.
- Loading branch information
Showing
2 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
<?php | ||
|
||
namespace YoastCS\Yoast\Tests\Utils; | ||
|
||
use YoastCS\Yoast\Tests\NonSniffTestCase; | ||
use YoastCS\Yoast\Utils\PathValidationHelper; | ||
|
||
/** | ||
* Tests for the YoastCS\Yoast\Utils\PathValidationHelper class. | ||
* | ||
* @coversDefaultClass \YoastCS\Yoast\Utils\PathValidationHelper | ||
* | ||
* @since 3.0.0 | ||
*/ | ||
final class PathValidationHelperTest extends NonSniffTestCase { | ||
|
||
/** | ||
* Default basepath. | ||
* | ||
* @var string | ||
*/ | ||
private const DIRTY_BASEPATH = '/base/path'; | ||
|
||
/** | ||
* Cleaned up version of the default basepath. | ||
* | ||
* @var string | ||
*/ | ||
private const CLEAN_BASEPATH = 'base/path/'; | ||
|
||
/** | ||
* Test converting a set of relative paths to absolute paths when no basepath is present. | ||
* | ||
* @covers ::relative_to_absolute | ||
* | ||
* @return void | ||
*/ | ||
public function test_relative_to_absolute_no_basepath() { | ||
$phpcsFile = $this->get_mock_file(); | ||
|
||
$this->assertSame( [], PathValidationHelper::relative_to_absolute( $phpcsFile, [ 'path' ] ) ); | ||
} | ||
|
||
/** | ||
* Test converting a set of relative paths to absolute paths when no paths where passed. | ||
* | ||
* @dataProvider data_relative_to_absolute_no_paths | ||
* @covers ::relative_to_absolute | ||
* | ||
* @param array<string> $input The input array. | ||
* | ||
* @return void | ||
*/ | ||
public function test_relative_to_absolute_no_paths( $input ) { | ||
$phpcsFile = $this->get_mock_file(); | ||
$phpcsFile->config->basepath = self::DIRTY_BASEPATH; | ||
|
||
$this->assertSame( [], PathValidationHelper::relative_to_absolute( $phpcsFile, $input ) ); | ||
} | ||
|
||
/** | ||
* Data provider. | ||
* | ||
* @see test_relative_to_absolute_no_paths() For the array format. | ||
* | ||
* @return array<string, array<string, array<string>>> | ||
*/ | ||
public static function data_relative_to_absolute_no_paths() { | ||
return [ | ||
'empty array' => [ | ||
'input' => [], | ||
], | ||
'array with only empty values' => [ | ||
'input' => [ | ||
'', | ||
' ', | ||
' ', | ||
], | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* Test converting a set of relative paths to absolute paths. | ||
* | ||
* @dataProvider data_relative_to_absolute | ||
* @covers ::relative_to_absolute | ||
* | ||
* @param array<string> $input The input array. | ||
* @param array<string> $expected The expected function output. | ||
* | ||
* @return void | ||
*/ | ||
public function test_relative_to_absolute( $input, $expected ) { | ||
$phpcsFile = $this->get_mock_file(); | ||
$phpcsFile->config->basepath = self::DIRTY_BASEPATH; | ||
|
||
$this->assertSame( $expected, PathValidationHelper::relative_to_absolute( $phpcsFile, $input ) ); | ||
} | ||
|
||
/** | ||
* Data provider. | ||
* | ||
* @see test_relative_to_absolute() For the array format. | ||
* | ||
* @return array<string, array<string, array<string>>> | ||
*/ | ||
public static function data_relative_to_absolute() { | ||
return [ | ||
'all cases' => [ | ||
'input' => [ | ||
'../walking/up/', | ||
'/walking/../up/', | ||
'/walking/up/../', | ||
' . ', | ||
'.', | ||
'./', | ||
'.\\', | ||
'./some/path', | ||
'./some/path/to/file.ext', | ||
'/some/path', | ||
'/some/path/to/file.ext', | ||
'some/path', | ||
'some/path/to/file.ext', | ||
'\some\path', | ||
'\some\path\to\file.ext', | ||
'.\some\path', | ||
'.\some\path\to\file.ext', | ||
], | ||
'expected' => [ | ||
' . ' => self::CLEAN_BASEPATH, | ||
'.' => self::CLEAN_BASEPATH, | ||
'./' => self::CLEAN_BASEPATH, | ||
'.\\' => self::CLEAN_BASEPATH, | ||
'./some/path' => self::CLEAN_BASEPATH . 'some/path/', | ||
'./some/path/to/file.ext' => self::CLEAN_BASEPATH . 'some/path/to/file.ext', | ||
'/some/path' => self::CLEAN_BASEPATH . 'some/path/', | ||
'/some/path/to/file.ext' => self::CLEAN_BASEPATH . 'some/path/to/file.ext', | ||
'some/path' => self::CLEAN_BASEPATH . 'some/path/', | ||
'some/path/to/file.ext' => self::CLEAN_BASEPATH . 'some/path/to/file.ext', | ||
'\some\path' => self::CLEAN_BASEPATH . 'some/path/', | ||
'\some\path\to\file.ext' => self::CLEAN_BASEPATH . 'some/path/to/file.ext', | ||
'.\some\path' => self::CLEAN_BASEPATH . 'some/path/', | ||
'.\some\path\to\file.ext' => self::CLEAN_BASEPATH . 'some/path/to/file.ext', | ||
], | ||
], | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
namespace YoastCS\Yoast\Utils; | ||
|
||
use PHP_CodeSniffer\Files\File; | ||
|
||
/** | ||
* Utility class containing methods for validating paths. | ||
* | ||
* --------------------------------------------------------------------------------------------- | ||
* This class is only intended for internal use by YoastCS and is not part of the public API. | ||
* This also means that it has no promise of backward compatibility. Use at your own risk. | ||
* --------------------------------------------------------------------------------------------- | ||
* | ||
* @internal | ||
* | ||
* @since 3.0.0 | ||
*/ | ||
final class PathValidationHelper { | ||
|
||
/** | ||
* Convert an array with relative paths to an array with absolute paths. | ||
* | ||
* Note: path walking is prohibited and relative paths containing ".." will be ignored. | ||
* | ||
* @param File $phpcsFile The current file being scanned. | ||
* @param array<string> $relative_paths Array of relative paths which should become absolute paths. | ||
* Paths are expected to be relative to the "basepath" setting. | ||
* | ||
* @return array<string, string> Array of absolute paths or an empty array if the conversion could not be executed. | ||
* The array will contain the original relative paths as the keys and the absolute paths | ||
* as the values. | ||
* Note: multiple relative paths may result in the same absolute path. | ||
* The values are not guaranteed to be unique! | ||
*/ | ||
public static function relative_to_absolute( File $phpcsFile, array $relative_paths ) { | ||
$absolute = []; | ||
|
||
if ( ! isset( $phpcsFile->config->basepath ) ) { | ||
// No use continuing as we can't turn relative paths into absolute paths. | ||
return $absolute; | ||
} | ||
|
||
$base_path = PathHelper::normalize_path( $phpcsFile->config->basepath ); | ||
|
||
foreach ( $relative_paths as $path ) { | ||
$result_path = \trim( $path ); | ||
$result_path = PathHelper::normalize_path( $result_path ); | ||
|
||
if ( $result_path === '' ) { | ||
continue; | ||
} | ||
|
||
if ( \strpos( $result_path, '..' ) !== false ) { | ||
// Ignore paths containing path walking. | ||
continue; | ||
} | ||
|
||
if ( $result_path === './' ) { | ||
$absolute[ $path ] = $base_path; | ||
continue; | ||
} | ||
|
||
if ( \strpos( $result_path, './' ) === 0 ) { | ||
$result_path = \substr( $result_path, 2 ); | ||
} | ||
|
||
$absolute[ $path ] = $base_path . $result_path; | ||
} | ||
|
||
return $absolute; | ||
} | ||
} |