diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4008efa1b4d4e..a324657fad6f7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -82,6 +82,7 @@ /packages/scripts @gziolo @ntwb @nerrad @ajitbohra @ryanwelcher /packages/stylelint-config @ntwb /test/e2e @kevin940726 @Mamaduka +/test/php/gutenberg-coding-standards @anton-vlasenko # UI Components /packages/components @ajitbohra diff --git a/composer.json b/composer.json index 3f16ba495a94c..134e366befdb9 100644 --- a/composer.json +++ b/composer.json @@ -32,8 +32,18 @@ "wp-coding-standards/wpcs": "^2.2", "sirbrillig/phpcs-variable-analysis": "^2.8", "spatie/phpunit-watcher": "^1.23", - "yoast/phpunit-polyfills": "^1.0" + "yoast/phpunit-polyfills": "^1.0", + "gutenberg/gutenberg-coding-standards": "@dev" }, + "repositories": [ + { + "type": "path", + "url": "./test/php/gutenberg-coding-standards", + "options": { + "symlink": false + } + } + ], "require": { "composer/installers": "~1.0" }, diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 816f7e414ad79..41120a882ed23 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -32,6 +32,10 @@ * @since 6.3.0 */ +if ( class_exists( 'WP_Duotone_Gutenberg' ) ) { + return; +} + /** * Manages duotone block supports and global styles. * diff --git a/lib/class-wp-theme-json-data-gutenberg.php b/lib/class-wp-theme-json-data-gutenberg.php index 2e5ea474346a9..db0737ebea08b 100644 --- a/lib/class-wp-theme-json-data-gutenberg.php +++ b/lib/class-wp-theme-json-data-gutenberg.php @@ -6,6 +6,10 @@ * @since 6.1.0 */ +if ( class_exists( 'WP_Theme_JSON_Data_Gutenberg' ) ) { + return; +} + /** * Class to provide access to update a theme.json structure. */ diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 0745ee06b84a2..60e69632eedb6 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -6,6 +6,10 @@ * @since 5.8.0 */ +if ( class_exists( 'WP_Theme_JSON_Gutenberg' ) ) { + return; +} + /** * Class that encapsulates the processing of structures that adhere to the theme.json spec. * diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php index 1e825e3c6bbe4..39721742946cd 100644 --- a/lib/class-wp-theme-json-resolver-gutenberg.php +++ b/lib/class-wp-theme-json-resolver-gutenberg.php @@ -6,6 +6,10 @@ * @since 5.8.0 */ +if ( class_exists( 'WP_Theme_JSON_Resolver_Gutenberg' ) ) { + return; +} + /** * Class that abstracts the processing of the different data sources * for site-level config and offers an API to work with them. diff --git a/lib/compat/wordpress-6.2/html-api/class-wp-html-attribute-token.php b/lib/compat/wordpress-6.2/html-api/class-wp-html-attribute-token.php index 2c52164a979f0..cc03c1441ee04 100644 --- a/lib/compat/wordpress-6.2/html-api/class-wp-html-attribute-token.php +++ b/lib/compat/wordpress-6.2/html-api/class-wp-html-attribute-token.php @@ -7,6 +7,10 @@ * @since 6.2.0 */ +if ( class_exists( 'WP_HTML_Attribute_Token' ) ) { + return; +} + /** * Data structure for the attribute token that allows to drastically improve performance. * diff --git a/lib/compat/wordpress-6.2/html-api/class-wp-html-span.php b/lib/compat/wordpress-6.2/html-api/class-wp-html-span.php index d92778cd3a222..e38bc55192317 100644 --- a/lib/compat/wordpress-6.2/html-api/class-wp-html-span.php +++ b/lib/compat/wordpress-6.2/html-api/class-wp-html-span.php @@ -7,6 +7,10 @@ * @since 6.2.0 */ +if ( class_exists( 'WP_HTML_Span' ) ) { + return; +} + /** * Represents a textual span inside an HTML document. * diff --git a/lib/compat/wordpress-6.2/html-api/class-wp-html-tag-processor.php b/lib/compat/wordpress-6.2/html-api/class-wp-html-tag-processor.php index 7edb67f9f0423..d61180074f608 100644 --- a/lib/compat/wordpress-6.2/html-api/class-wp-html-tag-processor.php +++ b/lib/compat/wordpress-6.2/html-api/class-wp-html-tag-processor.php @@ -26,6 +26,10 @@ * @since 6.2.0 */ +if ( class_exists( 'WP_HTML_Tag_Processor' ) ) { + return; +} + /** * Modifies attributes in an HTML document for tags matching a query. * diff --git a/lib/compat/wordpress-6.2/html-api/class-wp-html-text-replacement.php b/lib/compat/wordpress-6.2/html-api/class-wp-html-text-replacement.php index 912b4a56a5eb4..b3f70c8e7c57f 100644 --- a/lib/compat/wordpress-6.2/html-api/class-wp-html-text-replacement.php +++ b/lib/compat/wordpress-6.2/html-api/class-wp-html-text-replacement.php @@ -7,6 +7,10 @@ * @since 6.2.0 */ +if ( class_exists( 'WP_HTML_Text_Replacement' ) ) { + return; +} + /** * Data structure used to replace existing content from start to end that allows to drastically improve performance. * diff --git a/lib/compat/wordpress-6.2/rest-api.php b/lib/compat/wordpress-6.2/rest-api.php index c0f098fa6893a..97f7daecdff2f 100644 --- a/lib/compat/wordpress-6.2/rest-api.php +++ b/lib/compat/wordpress-6.2/rest-api.php @@ -91,43 +91,46 @@ function gutenberg_modify_rest_sidebars_response( $response ) { } add_filter( 'rest_prepare_sidebar', 'gutenberg_modify_rest_sidebars_response' ); - -/** - * Add the `block_types` value to the `pattern-directory-item` schema. - * - * @since 6.2.0 Added 'block_types' property. - */ -function add_block_pattern_block_types_schema() { - register_rest_field( - 'pattern-directory-item', - 'block_types', - array( - 'schema' => array( - 'description' => __( 'The block types which can use this pattern.', 'gutenberg' ), - 'type' => 'array', - 'uniqueItems' => true, - 'items' => array( 'type' => 'string' ), - 'context' => array( 'view', 'embed' ), - ), - ) - ); +if ( ! function_exists( 'add_block_pattern_block_types_schema' ) ) { + /** + * Add the `block_types` value to the `pattern-directory-item` schema. + * + * @since 6.2.0 Added 'block_types' property. + */ + function add_block_pattern_block_types_schema() { + register_rest_field( + 'pattern-directory-item', + 'block_types', + array( + 'schema' => array( + 'description' => __( 'The block types which can use this pattern.', 'gutenberg' ), + 'type' => 'array', + 'uniqueItems' => true, + 'items' => array( 'type' => 'string' ), + 'context' => array( 'view', 'embed' ), + ), + ) + ); + } } add_filter( 'rest_api_init', 'add_block_pattern_block_types_schema' ); -/** - * Add the `block_types` value into the API response. - * - * @since 6.2.0 Added 'block_types' property. - * - * @param WP_REST_Response $response The response object. - * @param object $raw_pattern The unprepared pattern. - */ -function filter_block_pattern_response( $response, $raw_pattern ) { - $data = $response->get_data(); - $data['block_types'] = array_map( 'sanitize_text_field', $raw_pattern->meta->wpop_block_types ); - $response->set_data( $data ); - return $response; +if ( ! function_exists( 'filter_block_pattern_response' ) ) { + /** + * Add the `block_types` value into the API response. + * + * @since 6.2.0 Added 'block_types' property. + * + * @param WP_REST_Response $response The response object. + * @param object $raw_pattern The unprepared pattern. + */ + function filter_block_pattern_response( $response, $raw_pattern ) { + $data = $response->get_data(); + $data['block_types'] = array_map( 'sanitize_text_field', $raw_pattern->meta->wpop_block_types ); + $response->set_data( $data ); + return $response; + } } add_filter( 'rest_prepare_block_pattern', 'filter_block_pattern_response', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/kses.php b/lib/compat/wordpress-6.3/kses.php index 23eee580f831a..b0b7356d2dac1 100644 --- a/lib/compat/wordpress-6.3/kses.php +++ b/lib/compat/wordpress-6.3/kses.php @@ -7,21 +7,23 @@ * @package gutenberg */ -/** - * Mark CSS safe if it contains grid functions - * - * This function should not be backported to core. - * - * @param bool $allow_css Whether the CSS is allowed. - * @param string $css_test_string The CSS to test. - */ -function allow_grid_functions_in_styles( $allow_css, $css_test_string ) { - if ( preg_match( - '/^grid-template-columns:\s*repeat\([0-9,a-z-\s\(\)]*\)$/', - $css_test_string - ) ) { - return true; +if ( ! function_exists( 'allow_grid_functions_in_styles' ) ) { + /** + * Mark CSS safe if it contains grid functions + * + * This function should not be backported to core. + * + * @param bool $allow_css Whether the CSS is allowed. + * @param string $css_test_string The CSS to test. + */ + function allow_grid_functions_in_styles( $allow_css, $css_test_string ) { + if ( preg_match( + '/^grid-template-columns:\s*repeat\([0-9,a-z-\s\(\)]*\)$/', + $css_test_string + ) ) { + return true; + } + return $allow_css; } - return $allow_css; } add_filter( 'safecss_filter_attr_allow_css', 'allow_grid_functions_in_styles', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/rest-api.php b/lib/compat/wordpress-6.3/rest-api.php index 90898c0b71e24..ecb8f52392fef 100644 --- a/lib/compat/wordpress-6.3/rest-api.php +++ b/lib/compat/wordpress-6.3/rest-api.php @@ -52,12 +52,13 @@ function gutenberg_update_templates_template_parts_rest_controller( $args, $post } add_filter( 'register_post_type_args', 'gutenberg_update_templates_template_parts_rest_controller', 10, 2 ); -/** - * Add the `modified` value to the `wp_template` schema. - * - * @since 6.3.0 Added 'modified' property and response value. - */ -function add_modified_wp_template_schema() { +if ( ! function_exists( 'add_modified_wp_template_schema' ) ) { + /** + * Add the `modified` value to the `wp_template` schema. + * + * @since 6.3.0 Added 'modified' property and response value. + */ + function add_modified_wp_template_schema() { register_rest_field( array( 'wp_template', 'wp_template_part' ), 'modified', @@ -80,6 +81,7 @@ function add_modified_wp_template_schema() { }, ) ); + } } add_filter( 'rest_api_init', 'add_modified_wp_template_schema' ); diff --git a/lib/compat/wordpress-6.3/theme-previews.php b/lib/compat/wordpress-6.3/theme-previews.php index 26153d74878b5..e885d389b94fe 100644 --- a/lib/compat/wordpress-6.3/theme-previews.php +++ b/lib/compat/wordpress-6.3/theme-previews.php @@ -51,14 +51,15 @@ function gutenberg_attach_theme_preview_middleware() { ); } -/** - * Temporary function to add a live preview button to block themes. - * Remove when https://core.trac.wordpress.org/ticket/58190 lands. - */ -function add_live_preview_button() { - global $pagenow; - if ( 'themes.php' === $pagenow ) { - ?> +if ( ! function_exists( 'add_live_preview_button' ) ) { + /** + * Temporary function to add a live preview button to block themes. + * Remove when https://core.trac.wordpress.org/ticket/58190 lands. + */ + function add_live_preview_button() { + global $pagenow; + if ( 'themes.php' === $pagenow ) { + ?> - +if ( ! function_exists( 'block_theme_activate_nonce' ) ) { + /** + * Adds a nonce for the theme activation link. + */ + function block_theme_activate_nonce() { + $nonce_handle = 'switch-theme_' . gutenberg_get_theme_preview_path(); + ?> - -
-

- -
- - - -
-
- +
+

+ +
+ + + +
+
+ ./vendor/* + ./test/php/gutenberg-coding-standards/* @@ -109,4 +110,19 @@ /phpunit/* + + + + ./phpunit/* + ./packages/* + ./bin/generate-gutenberg-php + + + + + + + + + diff --git a/test/php/gutenberg-coding-standards/.gitignore b/test/php/gutenberg-coding-standards/.gitignore new file mode 100644 index 0000000000000..bfec4c3c303b1 --- /dev/null +++ b/test/php/gutenberg-coding-standards/.gitignore @@ -0,0 +1,5 @@ +vendor +composer.lock +phpunit.xml +phpcs.xml +.phpcs.xml diff --git a/test/php/gutenberg-coding-standards/.phpcs.xml.dist b/test/php/gutenberg-coding-standards/.phpcs.xml.dist new file mode 100644 index 0000000000000..d6862f9a00fa9 --- /dev/null +++ b/test/php/gutenberg-coding-standards/.phpcs.xml.dist @@ -0,0 +1,88 @@ + + + + The Coding standard for the Gutenberg Coding Standards itself. + + + + . + + + */vendor/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php new file mode 100644 index 0000000000000..65c42071192b4 --- /dev/null +++ b/test/php/gutenberg-coding-standards/Gutenberg/Sniffs/CodeAnalysis/GuardedFunctionAndClassNamesSniff.php @@ -0,0 +1,221 @@ +onRegisterEvent(); + + return array( T_FUNCTION, T_CLASS ); + } + + /** + * Processes function and class tokens. + * + * @param File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process( File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[ $stackPtr ]; + + if ( 'T_FUNCTION' === $token['type'] ) { + $this->processFunctionToken( $phpcsFile, $stackPtr ); + return; + } + + if ( 'T_CLASS' === $token['type'] ) { + $this->processClassToken( $phpcsFile, $stackPtr ); + } + } + + /** + * Functions should be wrapped with !function_exists() to avoid fatal errors. + * E.g.: + * if ( ! function_exists( 'wp_get_navigation' ) ) { + * function wp_get_navigation( $slug ) { ... } + * } + * + * @param File $phpcsFile The file being scanned. + * @param int $stackPointer The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + private function processFunctionToken( File $phpcsFile, $stackPointer ) { + $tokens = $phpcsFile->getTokens(); + $functionToken = $phpcsFile->findNext( T_STRING, $stackPointer ); + + $wrappingTokensToCheck = array( + T_CLASS, + T_INTERFACE, + T_TRAIT, + ); + + foreach ( $wrappingTokensToCheck as $wrappingTokenToCheck ) { + if ( false !== $phpcsFile->getCondition( $functionToken, $wrappingTokenToCheck, false ) ) { + // This sniff only processes functions, not class methods. + return; + } + } + + $name = $tokens[ $functionToken ]['content']; + foreach ( $this->functionsWhiteList as $functionRegExp ) { + if ( preg_match( $functionRegExp, $name ) ) { + // Ignore whitelisted function names. + return; + } + } + + $errorMessage = sprintf( 'The "%s()" function should be guarded against redeclaration.', $name ); + + $wrappingIfToken = $phpcsFile->getCondition( $functionToken, T_IF, false ); + if ( false === $wrappingIfToken ) { + $phpcsFile->addError( $errorMessage, $functionToken, 'FunctionNotGuardedAgainstRedeclaration' ); + + return; + } + + $content = $phpcsFile->getTokensAsString( $wrappingIfToken, $functionToken - $wrappingIfToken ); + + $regexp = sprintf( '/if\s*\(\s*!\s*function_exists\s*\(\s*(\'|")%s(\'|")/', preg_quote( $name, '/' ) ); + $result = preg_match( $regexp, $content ); + if ( 1 !== $result ) { + $phpcsFile->addError( $errorMessage, $functionToken, 'FunctionNotGuardedAgainstRedeclaration' ); + } + } + + /** + * Classes should be wrapped with !function_exists() to avoid fatal errors. + * E.g.: + * if ( class_exists( 'WP_Navigation' ) ) { + * return; + * } + * + * Alternatively: + * + * if ( ! class_exists( 'WP_Navigation' ) ) { + * class WP_Navigation { ... } + * } + * + * @param File $phpcsFile The file being scanned. + * @param int $stackPointer The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + private function processClassToken( File $phpcsFile, $stackPointer ) { + $tokens = $phpcsFile->getTokens(); + $classToken = $phpcsFile->findNext( T_STRING, $stackPointer ); + $className = $tokens[ $classToken ]['content']; + + foreach ( $this->classesWhiteList as $classnameRegExp ) { + if ( preg_match( $classnameRegExp, $className ) ) { + // Ignore whitelisted class names. + return; + } + } + + $errorMessage = sprintf( 'The "%s" class should be guarded against redeclaration.', $className ); + + $wrappingIfToken = $phpcsFile->getCondition( $classToken, T_IF, false ); + if ( false !== $wrappingIfToken ) { + $endOfWrappingIfToken = $phpcsFile->findEndOfStatement( $wrappingIfToken ); + $content = $phpcsFile->getTokensAsString( $wrappingIfToken, $endOfWrappingIfToken - $wrappingIfToken ); + $regexp = sprintf( '/if\s*\(\s*!\s*class_exists\s*\(\s*(\'|")%s(\'|")/', preg_quote( $className, '/' ) ); + $result = preg_match( $regexp, $content ); + if ( 1 === $result ) { + return; + } + } + + $previousIfToken = $phpcsFile->findPrevious( T_IF, $classToken ); + if ( false === $previousIfToken ) { + $phpcsFile->addError( $errorMessage, $classToken, 'ClassNotGuardedAgainstRedeclaration' ); + + return; + } + + $endOfPreviousIfToken = $phpcsFile->findEndOfStatement( $previousIfToken ); + $content = $phpcsFile->getTokensAsString( $previousIfToken, $endOfPreviousIfToken - $previousIfToken ); + $regexp = sprintf( '/if\s*\(\s*class_exists\s*\(\s*(\'|")%s(\'|")/', preg_quote( $className, '/' ) ); + $result = preg_match( $regexp, $content ); + + if ( 1 === $result ) { + $returnToken = $phpcsFile->findNext( T_RETURN, $previousIfToken, $endOfPreviousIfToken ); + if ( false !== $returnToken ) { + return; + } + } + + $phpcsFile->addError( $errorMessage, $classToken, 'ClassNotGuardedAgainstRedeclaration' ); + } + + /** + * The purpose of this method is to sanitize the input data + * after the properties have been set. + */ + private function onRegisterEvent() { + $this->functionsWhiteList = self::sanitize( $this->functionsWhiteList ); + $this->classesWhiteList = self::sanitize( $this->classesWhiteList ); + } + + /** + * Input data needs to be sanitized. + * + * @param array $values The values being sanitized. + * + * @return array + */ + private static function sanitize( $values ) { + $values = array_map( 'trim', $values ); + + return array_filter( $values ); + } +} diff --git a/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.inc b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.inc new file mode 100644 index 0000000000000..5db9946d68ae3 --- /dev/null +++ b/test/php/gutenberg-coding-standards/Gutenberg/Tests/CodeAnalysis/GuardedFunctionAndClassNamesUnitTest.inc @@ -0,0 +1,26 @@ + => + */ + public function getErrorList() { + return array( + 17 => 1, + 25 => 1, + ); + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } +} diff --git a/test/php/gutenberg-coding-standards/Gutenberg/ruleset.xml b/test/php/gutenberg-coding-standards/Gutenberg/ruleset.xml new file mode 100644 index 0000000000000..e899c9bed0528 --- /dev/null +++ b/test/php/gutenberg-coding-standards/Gutenberg/ruleset.xml @@ -0,0 +1,8 @@ + + + + Gutenberg Coding Standards + + + + diff --git a/test/php/gutenberg-coding-standards/README.md b/test/php/gutenberg-coding-standards/README.md new file mode 100644 index 0000000000000..51f6574fa2053 --- /dev/null +++ b/test/php/gutenberg-coding-standards/README.md @@ -0,0 +1,3 @@ +# Gutenberg Coding Standards for Gutenberg + +This project is a collection of [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) rules (sniffs) to validate code developed for Gutenberg. It ensures code quality and adherence to coding conventions. \ No newline at end of file diff --git a/test/php/gutenberg-coding-standards/Tests/bootstrap.php b/test/php/gutenberg-coding-standards/Tests/bootstrap.php new file mode 100644 index 0000000000000..f28528bc1b972 --- /dev/null +++ b/test/php/gutenberg-coding-standards/Tests/bootstrap.php @@ -0,0 +1,86 @@ + true, +); + +$allStandards = PHP_CodeSniffer\Util\Standards::getInstalledStandards(); +$allStandards[] = 'Generic'; + +$standardsToIgnore = array(); +foreach ( $allStandards as $standard ) { + if ( isset( $gbcsStandards[ $standard ] ) === true ) { + continue; + } + + $standardsToIgnore[] = $standard; +} + +$standardsToIgnoreString = implode( ',', $standardsToIgnore ); + +// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv -- This is not production, but test code. +putenv( "PHPCS_IGNORE_TESTS={$standardsToIgnoreString}" ); + +// Clean up. +unset( $ds, $phpcsDir, $composerPHPCSPath, $allStandards, $standardsToIgnore, $standard, $standardsToIgnoreString ); diff --git a/test/php/gutenberg-coding-standards/composer.json b/test/php/gutenberg-coding-standards/composer.json new file mode 100644 index 0000000000000..f4ca88e49e2ae --- /dev/null +++ b/test/php/gutenberg-coding-standards/composer.json @@ -0,0 +1,65 @@ +{ + "name": "gutenberg/gutenberg-coding-standards", + "type": "phpcodesniffer-standard", + "description": "PHP_CodeSniffer rules (sniffs) to enforce Gutenberg coding conventions", + "keywords": [ + "phpcs", + "standards", + "static analysis", + "Gutenberg" + ], + "license": "MIT", + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/WordPress/gutenberg/graphs/contributors" + } + ], + "require": { + "php": ">=5.4", + "ext-filter": "*", + "squizlabs/php_codesniffer": "^3.7.2" + }, + "require-dev": { + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "dealerdirect/phpcodesniffer-composer-installer": "*", + "wp-coding-standards/wpcs": "^2.2" + }, + "suggest": { + "ext-mbstring": "For improved results" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "scripts": { + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --show-deprecated --exclude vendor --exclude .git" + ], + "check-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs" + ], + "fix-cs": [ + "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf" + ], + "run-tests": [ + "@php ./vendor/phpunit/phpunit/phpunit -c phpunit.xml.dist --filter Gutenberg ./vendor/squizlabs/php_codesniffer/tests/AllTests.php" + ], + "check-all": [ + "@lint", + "@check-cs", + "@run-tests" + ] + }, + "scripts-descriptions": { + "lint": "Lint PHP files against parse errors.", + "check-cs": "Run the PHPCS script against the entire codebase.", + "fix-cs": "Run the PHPCBF script to fix all the autofixable violations on the codebase.", + "run-tests": "Run all the unit tests for the Gutenberg Coding Standards sniffs.", + "check-all": "Run all checks (lint, phpcs) and tests." + } +} diff --git a/test/php/gutenberg-coding-standards/phpunit.xml.dist b/test/php/gutenberg-coding-standards/phpunit.xml.dist new file mode 100644 index 0000000000000..0e9d9cb5b7507 --- /dev/null +++ b/test/php/gutenberg-coding-standards/phpunit.xml.dist @@ -0,0 +1,16 @@ + + + + + + ./Gutenberg/Tests/ + + + +