diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..d247a587 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,45 @@ +name: Tests + +on: [ push, pull_request ] + +jobs: + lint: + name: Lint PHP files + runs-on: ubuntu-latest + strategy: + matrix: + php: + - '8.2' + - '8.3' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP version + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Lint PHP + run: find . -type f -name '*.php' ! -path "./.Build/*" -print0 | xargs -0 -n1 -P4 php -l -n | (! grep -v "No syntax errors detected" ) + + code-quality: + name: Code quality + runs-on: ubuntu-latest + env: + php: '8.2' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP version + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Install testing system + run: composer update --no-progress --prefer-dist --optimize-autoloader + + - name: Check PHP coding standards + run: | + make check-php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 00000000..77dc23d1 --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,76 @@ +setFinder( + (new Finder()) + ->in(__DIR__ . '/Documentation') + ) + ->setRiskyAllowed(true) + ->setRules([ + '@DoctrineAnnotation' => true, + // @todo: Switch to @PER-CS2.0 once php-cs-fixer's todo list is done: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues/7247 + '@PER-CS1.0' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'cast_spaces' => ['space' => 'none'], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'declare_parentheses' => true, + 'dir_constant' => true, + // @todo: Can be dropped once we enable @PER-CS2.0 + 'function_declaration' => [ + 'closure_fn_spacing' => 'none', + ], + 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']], + 'type_declaration_spaces' => true, + 'global_namespace_import' => ['import_classes' => false, 'import_constants' => false, 'import_functions' => false], + 'list_syntax' => ['syntax' => 'short'], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'method_argument_space' => true, + 'modernize_strpos' => true, + 'modernize_types_casting' => true, + 'native_function_casing' => true, + 'no_alias_functions' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_leading_namespace_whitespace' => true, + 'no_null_property_initialization' => true, + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_superfluous_elseif' => true, + 'no_trailing_comma_in_singleline' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unused_imports' => true, + 'no_useless_nullsafe_operator' => true, + 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], + 'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']], + 'php_unit_mock_short_will_return' => true, + 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], + 'phpdoc_no_access' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_scalar' => true, + 'phpdoc_trim' => true, + 'phpdoc_types' => true, + 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], + 'return_type_declaration' => ['space_before' => 'none'], + 'single_quote' => true, + 'single_space_around_construct' => true, + 'single_line_comment_style' => ['comment_types' => ['hash']], + // @todo: Can be dropped once we enable @PER-CS2.0 + 'single_line_empty_body' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arguments', 'arrays', 'match', 'parameters']], + 'whitespace_after_comma_in_array' => ['ensure_single_space' => true], + 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], + + // We need this for documentation! + 'no_useless_else' => false, // We want to preserve else with comments only + ]); diff --git a/Documentation/Installation/Deployer/_deploy.php b/Documentation/Installation/Deployer/_deploy.php index 45543797..acc0a05b 100644 --- a/Documentation/Installation/Deployer/_deploy.php +++ b/Documentation/Installation/Deployer/_deploy.php @@ -1,7 +1,9 @@ setHostname($node->getName()) @@ -20,7 +20,7 @@ '.ddev', '.git', $application->getOption('webDirectory') . '/fileadmin', - 'packages/**.sass' + 'packages/**.sass', ]) ->setOption(TYPO3\Surf\Task\TYPO3\CMS\FlushCachesTask::class . '[arguments]', []) ->addSymlink($application->getOption('webDirectory') . '/config/system/settings.php', '../../../../shared/Configuration/settings.php') @@ -35,26 +35,27 @@ function () use ($deployment, $application) { ->beforeTask( \TYPO3\Surf\Task\TYPO3\CMS\SetUpExtensionsTask::class, \TYPO3\Surf\Task\TYPO3\CMS\CompareDatabaseTask::class, - $application + $application, ) ->beforeStage( 'transfer', \TYPO3\Surf\Task\Php\WebOpcacheResetCreateScriptTask::class, - $application + $application, ) - ->afterStage('switch', + ->afterStage( + 'switch', \TYPO3\Surf\Task\Php\WebOpcacheResetExecuteTask::class, - $application + $application, ) // CreatePackageStatesTask is done by post-autoload-dump script and can be removed // https://github.com/TYPO3/TYPO3.CMS.BaseDistribution/blob/9.x/composer.json#L38 ->removeTask( \TYPO3\Surf\Task\TYPO3\CMS\CreatePackageStatesTask::class, - $application + $application, ) ->removeTask( \TYPO3\Surf\Task\TYPO3\CMS\CopyConfigurationTask::class, - $application + $application, ); - } + }, ); diff --git a/Makefile b/Makefile index 97039388..769332df 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,22 @@ help: ## Displays this list of targets with descriptions @echo "The following commands are available:\n" @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' +.PHONY: check +check: check-php + +.PHONY: check-php +check-php: + vendor/bin/php-cs-fixer check + .PHONY: docs docs: ## Generate projects docs (from "Documentation" directory) mkdir -p Documentation-GENERATED-temp docker run --rm --pull always -v "$(shell pwd)":/project -t ghcr.io/typo3-documentation/render-guides:latest --config=Documentation + +.PHONY: fix +fix: fix-php + +.PHONY: fix-php +fix-php: + vendor/bin/php-cs-fixer fix diff --git a/composer.json b/composer.json index b4f573bd..f498a76c 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,9 @@ "require": { "typo3/cms-core": "dev-main" }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.51" + }, "config": { "allow-plugins": { "typo3/cms-composer-installers": true,