Skip to content

Commit

Permalink
Refacto FileHelper to have consistent behavior with absolute and rela…
Browse files Browse the repository at this point in the history
…tive paths (#189)
  • Loading branch information
VincentLanglet authored Feb 9, 2024
1 parent e096ea2 commit 6cd086f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 66 deletions.
20 changes: 5 additions & 15 deletions src/Config/ConfigResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use TwigCsFixer\Cache\Manager\FileCacheManager;
use TwigCsFixer\Cache\Signature;
use TwigCsFixer\Exception\CannotResolveConfigException;
use TwigCsFixer\File\FileHelper;
use TwigCsFixer\File\Finder as TwigCsFinder;
use TwigCsFixer\Ruleset\Ruleset;

Expand Down Expand Up @@ -61,15 +62,15 @@ public function resolveConfig(
private function getConfig(?string $configPath = null): Config
{
if (null !== $configPath) {
return $this->getConfigFromPath($this->getAbsolutePath($configPath));
return $this->getConfigFromPath(FileHelper::getAbsolutePath($configPath, $this->workingDir));
}

$defaultPath = $this->getAbsolutePath(Config::DEFAULT_PATH);
$defaultPath = FileHelper::getAbsolutePath(Config::DEFAULT_PATH, $this->workingDir);
if (file_exists($defaultPath)) {
return $this->getConfigFromPath($defaultPath);
}

$defaultDistPath = $this->getAbsolutePath(Config::DEFAULT_DIST_PATH);
$defaultDistPath = FileHelper::getAbsolutePath(Config::DEFAULT_DIST_PATH, $this->workingDir);
if (file_exists($defaultDistPath)) {
return $this->getConfigFromPath($defaultDistPath);
}
Expand Down Expand Up @@ -145,23 +146,12 @@ private function resolveCacheManager(
}

return new FileCacheManager(
new CacheFileHandler($this->getAbsolutePath($cacheFile)),
new CacheFileHandler(FileHelper::getAbsolutePath($cacheFile, $this->workingDir)),
Signature::fromRuleset(
\PHP_VERSION,
InstalledVersions::getReference(self::PACKAGE_NAME) ?? '0',
$ruleset,
)
);
}

private function getAbsolutePath(string $path): string
{
$isAbsolutePath = '' !== $path && (
'/' === $path[0]
|| '\\' === $path[0]
|| 1 === preg_match('#^[a-zA-Z]:\\\\#', $path)
);

return $isAbsolutePath ? $path : $this->workingDir.\DIRECTORY_SEPARATOR.$path;
}
}
75 changes: 55 additions & 20 deletions src/File/FileHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,18 @@

namespace TwigCsFixer\File;

use Webmozart\Assert\Assert;

final class FileHelper
{
public static function getAbsolutePath(string $path, ?string $workingDir = null): string
{
$workingDir ??= @getcwd();
Assert::notFalse($workingDir, 'Cannot get the current working directory.');

return self::isAbsolutePath($path) ? $path : $workingDir.\DIRECTORY_SEPARATOR.$path;
}

public static function removeDot(string $fileName): string
{
if (!str_starts_with($fileName, '.')) {
Expand All @@ -21,9 +31,10 @@ public static function removeDot(string $fileName): string
public static function getFileName(
string $path,
?string $baseDir = null,
array $ignoredDir = []
array $ignoredDir = [],
?string $workingDir = null,
): ?string {
$split = self::splitPath($path, $baseDir, $ignoredDir);
$split = self::splitPath($path, $baseDir, $ignoredDir, $workingDir);
if ([] === $split) {
return null;
}
Expand All @@ -39,9 +50,10 @@ public static function getFileName(
public static function getDirectories(
string $path,
?string $baseDir = null,
array $ignoredDir = []
array $ignoredDir = [],
?string $workingDir = null,
): array {
$split = self::splitPath($path, $baseDir, $ignoredDir);
$split = self::splitPath($path, $baseDir, $ignoredDir, $workingDir);
array_pop($split);

return $split;
Expand All @@ -55,29 +67,52 @@ public static function getDirectories(
private static function splitPath(
string $path,
?string $baseDir = null,
array $ignoredDir = []
array $ignoredDir = [],
?string $workingDir = null,
): array {
$baseDir = trim($baseDir ?? '', \DIRECTORY_SEPARATOR);

if ('' === $baseDir || str_starts_with($path, $baseDir.\DIRECTORY_SEPARATOR)) {
$baseDirPosition = 0;
$baseDir .= \DIRECTORY_SEPARATOR;
} else {
$baseDir = \DIRECTORY_SEPARATOR.$baseDir.\DIRECTORY_SEPARATOR;
$baseDirPosition = strrpos($path, $baseDir);
if (false === $baseDirPosition) {
return [];
}
$baseDir = self::simplifyPath(self::getAbsolutePath($baseDir ?? '', $workingDir));
$path = self::simplifyPath(self::getAbsolutePath($path, $workingDir));

if (!str_starts_with($path, $baseDir.\DIRECTORY_SEPARATOR)) {
return [];
}

$path = substr($path, $baseDirPosition + \strlen($baseDir));
foreach ($ignoredDir as $ignoredDirectory) {
$ignoredDirectory = trim($ignoredDirectory, \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
if (str_starts_with($path, $ignoredDirectory)) {
$ignoredDirectory = self::simplifyPath(self::getAbsolutePath($ignoredDirectory, $baseDir));
if (str_starts_with($path, $ignoredDirectory.\DIRECTORY_SEPARATOR)) {
return [];
}
}

return explode(\DIRECTORY_SEPARATOR, $path);
return explode(\DIRECTORY_SEPARATOR, substr($path, \strlen($baseDir) + 1));
}

private static function isAbsolutePath(string $path): bool
{
return '' !== $path && (
'/' === $path[0]
|| '\\' === $path[0]
|| 1 === preg_match('#^[a-zA-Z]:\\\\#', $path)
);
}

private static function simplifyPath(string $absolutePath): string
{
if (!self::isAbsolutePath($absolutePath)) {
throw new \InvalidArgumentException('The path must be absolute.');
}

$parts = explode(\DIRECTORY_SEPARATOR, $absolutePath);

$result = [];
foreach ($parts as $part) {
if ('..' === $part) {
array_pop($result);
} elseif ('.' !== $part && '' !== $part) {
$result[] = $part;
}
}

return \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $result);
}
}
24 changes: 3 additions & 21 deletions tests/File/FileHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ public static function removeDotDataProvider(): iterable
* @dataProvider getFileNameDataProvider
*/
public function testGetFileName(
string $absolutePath,
string $path,
?string $baseDir,
array $ignoredDir,
?string $expected,
): void {
static::assertSame($expected, FileHelper::getFileName($absolutePath, $baseDir, $ignoredDir));
static::assertSame($expected, FileHelper::getFileName($path, $baseDir, $ignoredDir));
}

/**
Expand All @@ -66,12 +66,6 @@ public static function getFileNameDataProvider(): iterable
['directory'],
null,
];
yield [
__DIR__.'/Fixtures/directory/file.twig',
__DIR__.'/Fixtures',
['/directory'],
null,
];
yield [
__DIR__.'/Fixtures/directory/file.twig',
__DIR__.'/Fixtures',
Expand Down Expand Up @@ -104,7 +98,7 @@ public function testGetDirectories(
array $ignoredDir,
array $expected,
): void {
static::assertSame($expected, FileHelper::getDirectories($absolutePath, $baseDir, $ignoredDir));
static::assertSame($expected, FileHelper::getDirectories($absolutePath, $baseDir, $ignoredDir, __DIR__));
}

/**
Expand Down Expand Up @@ -136,12 +130,6 @@ public static function getDirectoriesDataProvider(): iterable
['directory'],
[],
];
yield [
__DIR__.'/Fixtures/directory/file.twig',
__DIR__.'/Fixtures',
['/directory'],
[],
];
yield [
__DIR__.'/Fixtures/directory/file.twig',
__DIR__.'/Fixtures',
Expand All @@ -161,12 +149,6 @@ public static function getDirectoriesDataProvider(): iterable
['Fixtures', 'directory'],
];

yield [
__DIR__.'/directory/foo/directory/file.twig',
'directory',
[],
[],
];
yield [
'/foo_directory/directory/file.twig',
'/',
Expand Down
16 changes: 8 additions & 8 deletions tests/Rules/File/DirectoryName/DirectoryNameRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public function testConfiguration(): void

public function testRule(): void
{
$this->checkRule(new DirectoryNameRule(baseDirectory: 'templates'), []);
$this->checkRule(new DirectoryNameRule(baseDirectory: __DIR__.'/templates'), []);
}

public function testRuleValidTemplatesDirectory(): void
{
$this->checkRule(
new DirectoryNameRule(baseDirectory: 'templates'),
new DirectoryNameRule(baseDirectory: __DIR__.'/templates'),
[],
__DIR__.'/templates/directory_name_rule_test/DirectoryNameRuleTest.twig'
);
Expand All @@ -51,26 +51,26 @@ public function testRuleValidTemplatesDirectory(): void
public function testRuleInvalidTemplatesDirectory(): void
{
$this->checkRule(
new DirectoryNameRule(baseDirectory: 'templates'),
new DirectoryNameRule(baseDirectory: __DIR__.'/templates'),
['DirectoryName.Error'],
__DIR__.'/templates/directoryNameRuleTest/DirectoryNameRuleTest.twig'
);
}

public function testRulePascalCase(): void
{
$this->checkRule(new DirectoryNameRule(DirectoryNameRule::PASCAL_CASE, baseDirectory: 'File'), []);
$this->checkRule(new DirectoryNameRule(DirectoryNameRule::PASCAL_CASE, baseDirectory: __DIR__.'/..'), []);
}

public function testRuleInvalidDirectory(): void
{
$this->checkRule(new DirectoryNameRule(baseDirectory: 'File'), ['DirectoryName.Error']);
$this->checkRule(new DirectoryNameRule(baseDirectory: __DIR__.'/..'), ['DirectoryName.Error']);
}

public function testRuleKebabCase(): void
{
$this->checkRule(
new DirectoryNameRule(DirectoryNameRule::KEBAB_CASE, baseDirectory: 'templates'),
new DirectoryNameRule(DirectoryNameRule::KEBAB_CASE, baseDirectory: __DIR__.'/templates'),
[],
__DIR__.'/templates/directory-name-rule-test/DirectoryNameRuleTest.twig',
);
Expand All @@ -79,7 +79,7 @@ public function testRuleKebabCase(): void
public function testRuleCamelCase(): void
{
$this->checkRule(
new DirectoryNameRule(DirectoryNameRule::CAMEL_CASE, baseDirectory: 'templates'),
new DirectoryNameRule(DirectoryNameRule::CAMEL_CASE, baseDirectory: __DIR__.'/templates'),
[],
__DIR__.'/templates/directoryNameRuleTest/DirectoryNameRuleTest.twig',
);
Expand All @@ -88,7 +88,7 @@ public function testRuleCamelCase(): void
public function testRuleIgnoredDirectory(): void
{
$this->checkRule(
new DirectoryNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles']),
new DirectoryNameRule(baseDirectory: __DIR__.'/templates', ignoredSubDirectories: ['bundles']),
[],
__DIR__.'/templates/bundles/directoryNameRuleTest/DirectoryNameRuleTest.twig'
);
Expand Down
4 changes: 2 additions & 2 deletions tests/Rules/File/FileName/FileNameRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ public function testRuleValidFileWithDot(): void

public function testRuleBaseDir(): void
{
$this->checkRule(new FileNameRule(baseDirectory: 'File'), [
$this->checkRule(new FileNameRule(baseDirectory: __DIR__.'/..'), [
'FileName.Error',
]);
}

public function testRuleIgnoredPath(): void
{
$this->checkRule(new FileNameRule(baseDirectory: 'File', ignoredSubDirectories: ['FileName']), []);
$this->checkRule(new FileNameRule(baseDirectory: __DIR__.'/..', ignoredSubDirectories: ['FileName']), []);
}
}

0 comments on commit 6cd086f

Please sign in to comment.