diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index 5e48d56..ef8837b 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -39,9 +39,6 @@ - - - @@ -77,6 +74,14 @@ ############################################################################# --> + + + + + + + + diff --git a/Yoast/Docs/Files/FileNameStandard.xml b/Yoast/Docs/Files/FileNameStandard.xml index 1d18549..957a4c3 100644 --- a/Yoast/Docs/Files/FileNameStandard.xml +++ b/Yoast/Docs/Files/FileNameStandard.xml @@ -65,6 +65,33 @@ class WPSEO_Utils {} + + + + Yoast_Output_Thing.php --> +Yoast_Output_Thing {} + ]]> + + + outline-something.php --> +Yoast_Outline_Something {} + ]]> + + + + diff --git a/Yoast/Sniffs/Files/FileNameSniff.php b/Yoast/Sniffs/Files/FileNameSniff.php index 2946d39..6192c2e 100644 --- a/Yoast/Sniffs/Files/FileNameSniff.php +++ b/Yoast/Sniffs/Files/FileNameSniff.php @@ -9,6 +9,7 @@ use PHPCSUtils\Utils\TextStrings; use YoastCS\Yoast\Utils\PathHelper; use YoastCS\Yoast\Utils\PathValidationHelper; +use YoastCS\Yoast\Utils\PSR4PathsTrait; /** * Ensures files comply with the Yoast file name rules. @@ -24,10 +25,15 @@ * have a "-functions" suffix. * * @since 0.5 - * @since 3.0.0 The sniff will now also be enforced for files only using the PHP short open tag. + * @since 3.0.0 - The sniff will now also be enforced for files only using the PHP short open tag. + * - The sniff now also has the ability to check for PSR-4 compliant file names. + * + * @uses \YoastCS\Yoast\Utils\PSR4PathsTrait::$psr4_paths */ final class FileNameSniff implements Sniff { + use PSR4PathsTrait; + /** * Object tokens to search for in a file. * @@ -192,13 +198,19 @@ public function process( File $phpcsFile, $stackPtr ) { $this->add_missing_basepath_warning( $phpcsFile ); } - if ( $this->is_file_excluded( $phpcsFile, $file ) === false ) { - $oo_structure = $phpcsFile->findNext( self::NAMED_OO_TOKENS, $stackPtr ); - if ( $oo_structure !== false ) { + $oo_structure = $phpcsFile->findNext( self::NAMED_OO_TOKENS, $stackPtr ); + if ( $oo_structure !== false ) { + + $oo_name = ObjectDeclarations::getName( $phpcsFile, $oo_structure ); - $oo_name = ObjectDeclarations::getName( $phpcsFile, $oo_structure ); + if ( ! empty( $oo_name ) ) { - if ( ! empty( $oo_name ) ) { + if ( $this->is_in_psr4_path( $phpcsFile, $file ) ) { + $error = 'Directory marked as a PSR-4 path. File names should 100%% match the name of the OO structure contained in the file for PSR-4 compliance.'; + $error_code = 'InvalidPSR4FileName'; + $expected = $oo_name; + } + elseif ( $this->is_file_excluded( $phpcsFile, $file ) === false ) { $this->validate_oo_prefixes(); if ( ! empty( $this->clean_oo_prefixes ) ) { foreach ( $this->clean_oo_prefixes as $prefix ) { @@ -239,15 +251,15 @@ public function process( File $phpcsFile, $stackPtr ) { } } } - else { - $has_function = $phpcsFile->findNext( \T_FUNCTION, $stackPtr ); - if ( $has_function !== false && $file_name !== 'functions' ) { - $error = 'Files containing function declarations should have "-functions" as a suffix.'; - $error_code = 'InvalidFunctionsFileName'; - - if ( \substr( $expected, -10 ) !== '-functions' ) { - $expected .= '-functions'; - } + } + elseif ( $this->is_file_excluded( $phpcsFile, $file ) === false ) { + $has_function = $phpcsFile->findNext( \T_FUNCTION, $stackPtr ); + if ( $has_function !== false && $file_name !== 'functions' ) { + $error = 'Files containing function declarations should have "-functions" as a suffix.'; + $error_code = 'InvalidFunctionsFileName'; + + if ( \substr( $expected, -10 ) !== '-functions' ) { + $expected .= '-functions'; } } } @@ -374,7 +386,7 @@ private function add_missing_basepath_warning( File $phpcsFile ) { } $phpcsFile->addWarning( - 'For the exclude property to work with relative file path files, the --basepath needs to be set.', + 'For the excluded files and the psr4 paths properties to work with relative file paths, the --basepath needs to be set.', 0, 'MissingBasePath' ); diff --git a/Yoast/Tests/Files/FileNameUnitTest.php b/Yoast/Tests/Files/FileNameUnitTest.php index 4711af0..0b04c8b 100644 --- a/Yoast/Tests/Files/FileNameUnitTest.php +++ b/Yoast/Tests/Files/FileNameUnitTest.php @@ -101,12 +101,41 @@ final class FileNameUnitTest extends AbstractSniffUnitTest { 'partial-file-disable.inc' => 1, 'Errorcode_Disable.inc' => 1, // The sniff can only be disabled completely, not by error code. + // PSR4 file names. + 'Some_Class.inc' => 0, + 'Some_Enum.inc' => 0, + 'Some_Interface.inc' => 0, + 'Some_Trait.inc' => 0, + 'Wrong_Class.inc' => 1, // Filename not in line with class name. + 'Wrong_Enum.inc' => 1, // Filename not in line with enum name. + 'Wrong_Interface.inc' => 1, // Filename not in line with interface name. + 'Wrong_Trait.inc' => 1, // Filename not in line with trait name. + 'wrong_case.inc' => 1, // Names are case-sensitive. + 'Wrong_Case_Too.inc' => 1, // Names are case-sensitive. + 'WPSEO_Prefixed.inc' => 0, // Prefixes should not be stripped for PSR4 file names. + 'Yoast_Prefixed.inc' => 0, // Prefixes should not be stripped for PSR4 file names. + 'Prefix_Stripped.inc' => 1, // Prefixes should not be stripped for PSR4 file names. + 'Not_Excluded.inc' => 1, // Exclusions do not apply to files where prefix stripping is not supported. + 'no-oo.inc' => 0, // Files not containing OO should follow the normal rules for PSR4 dirs. + 'no-oo-functions.inc' => 0, // Files containing only functions should follow the normal rules for PSR4 dirs. + 'missing-suffix.inc' => 1, // Files containing only functions should follow the normal rules for PSR4 dirs. + 'Multiple_Paths.inc' => 0, + 'Dot_Prefixed_Path.inc' => 0, + 'illegal-psr4-path.inc' => 0, // PSR4 path ignored, so normal rules apply. + 'Illegal_PSR4_Path.inc' => 1, // PSR4 path ignored, so normal rules apply. + /* * In /. */ // Fall-back file in case glob() fails. 'FileNameUnitTest.inc' => 1, + + // PSR4 related, PSR4 dir is root dir. + 'not-in-psr4-path.inc' => 0, + 'not-in-psr4-path-wrong-name.inc' => 1, // Filename not in line with class name, non-PSR4. + 'PSR4_Path_Is_Root_Path.inc' => 0, + 'PSR4_Path_Root_Wrong_Name.inc' => 1, // Filename not in line with class name, PSR4. ]; /** @@ -118,7 +147,7 @@ final class FileNameUnitTest extends AbstractSniffUnitTest { * @return void */ public function setCliValues( $filename, $config ): void { - if ( $filename === 'no-basepath.inc' ) { + if ( $filename === 'no-basepath.inc' || $filename === 'no-basepath-psr4.inc' ) { return; } @@ -169,7 +198,12 @@ public function getErrorList( string $testFile = '' ): array { * @return array Key is the line number, value is the number of expected warnings. */ public function getWarningList( string $testFile = '' ): array { - if ( $testFile === 'no-basepath.inc' ) { + /* + * Note: no warning for the 'no-basepath.inc' file as the warning will only be thrown once. + * Also note that in which file the warning is thrown, relies on the sorting order of the + * test files, which could change. + */ + if ( $testFile === 'no-basepath-psr4.inc' ) { return [ 1 => 1, ]; diff --git a/Yoast/Tests/Files/FileNameUnitTests/PSR4/Dot_Prefixed_Path.inc b/Yoast/Tests/Files/FileNameUnitTests/PSR4/Dot_Prefixed_Path.inc new file mode 100644 index 0000000..790bc3c --- /dev/null +++ b/Yoast/Tests/Files/FileNameUnitTests/PSR4/Dot_Prefixed_Path.inc @@ -0,0 +1,8 @@ + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>./PSR4 + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>PSR4/../PSR4/../ + + +phpcs:set Yoast.Files.FileName psr4_paths[] PrefixA\=>Other_Path/,PrefixB=>/PSR4/,PrefixC\=>/Deep/Path/Sub/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ +phpcs:set Yoast.Files.FileName excluded_files_strict_check[] PSR4/Not_Excluded.inc + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ +phpcs:set Yoast.Files.FileName oo_prefixes[] wpseo,yoast + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\=>PSR4 + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4 + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ +phpcs:set Yoast.Files.FileName oo_prefixes[] wpseo,yoast + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>PSR4 + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4 + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] PrefixA=>/src/,PrefixB=>/PSR4/ +phpcs:set Yoast.Files.FileName oo_prefixes[] wpseo,yoast + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>PSR4/../PSR4/../ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>. + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>. + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + + +phpcs:set Yoast.Files.FileName psr4_paths[] Prefix\\=>/PSR4/ + +