diff --git a/src/Rules/File/FileNameRule.php b/src/Rules/File/FileNameRule.php index d863c3b8..0a5a2919 100644 --- a/src/Rules/File/FileNameRule.php +++ b/src/Rules/File/FileNameRule.php @@ -27,6 +27,7 @@ public function __construct( private string $case = self::SNAKE_CASE, private ?string $baseDirectory = null, private array $ignoredSubDirectories = [], + private string $allowedPrefix = '', ) { } @@ -36,6 +37,7 @@ public function getConfiguration(): array 'case' => $this->case, 'baseDirectory' => $this->baseDirectory, 'ignoredSubDirectories' => $this->ignoredSubDirectories, + 'allowedPrefix' => $this->allowedPrefix, ]; } @@ -59,6 +61,12 @@ protected function process(int $tokenPosition, array $tokens): void // in order to avoid conflict with some file extensions. $fileName = explode('.', FileHelper::removeDot($fileName))[0]; + $prefix = ''; + if (str_starts_with($fileName, $this->allowedPrefix)) { + $prefix = $this->allowedPrefix; + $fileName = substr($fileName, \strlen($this->allowedPrefix)); + } + $expected = match ($this->case) { self::SNAKE_CASE => StringUtil::toSnakeCase($fileName), self::CAMEL_CASE => StringUtil::toCamelCase($fileName), @@ -68,7 +76,7 @@ protected function process(int $tokenPosition, array $tokens): void if ($expected !== $fileName) { $this->addFileError( - sprintf('The file name must use %s; expected %s.', $this->case, $expected), + sprintf('The file name must use %s; expected %s.', $this->case, $prefix.$expected), $token, ); } diff --git a/src/Standard/Symfony.php b/src/Standard/Symfony.php index 97929be9..31dbfba6 100644 --- a/src/Standard/Symfony.php +++ b/src/Standard/Symfony.php @@ -13,6 +13,7 @@ * * @see https://twig.symfony.com/doc/3.x/coding_standards.html * @see https://symfony.com/doc/current/templates.html#template-naming + * @see https://symfony.com/doc/current/best_practices.html#templates */ final class Symfony implements StandardInterface { @@ -20,7 +21,7 @@ public function getRules(): array { return [ ...(new Twig())->getRules(), - new FileNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles']), + new FileNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles'], allowedPrefix: '_'), new DirectoryNameRule(baseDirectory: 'templates', ignoredSubDirectories: ['bundles']), new FileExtensionRule(), ]; diff --git a/tests/Rules/File/FileName/FileNameRuleTest.php b/tests/Rules/File/FileName/FileNameRuleTest.php index 8ea86248..4d162b9b 100644 --- a/tests/Rules/File/FileName/FileNameRuleTest.php +++ b/tests/Rules/File/FileName/FileNameRuleTest.php @@ -89,4 +89,10 @@ public function testRuleIgnoredPath(): void { $this->checkRule(new FileNameRule(baseDirectory: __DIR__.'/..', ignoredSubDirectories: ['FileName']), []); } + + public function testRuleAllowedPrefix(): void + { + $this->checkRule(new FileNameRule(), ['FileName.Error'], __DIR__.'/_file_name_rule_test.twig'); + $this->checkRule(new FileNameRule(allowedPrefix: '_'), [], __DIR__.'/_file_name_rule_test.twig'); + } } diff --git a/tests/Rules/File/FileName/_file_name_rule_test.twig b/tests/Rules/File/FileName/_file_name_rule_test.twig new file mode 100644 index 00000000..4a584e49 --- /dev/null +++ b/tests/Rules/File/FileName/_file_name_rule_test.twig @@ -0,0 +1 @@ +Nothing