From dc3f4f2d83194b930e1f892afd33b9f42828e4b6 Mon Sep 17 00:00:00 2001 From: Sybille Peters Date: Sat, 5 Apr 2025 13:08:54 +0200 Subject: [PATCH 1/2] [TASK] Add checks and tests for GitHub workflows Add some checks and tests (in particular php-cs-fixer) which were already defined in composer.json, but some pieces were missing. - remove repository for powermail "pro" from composer.json because it will prevent "composer install" from working without credentials and is not need currently for v12. (Alternatively, the repository could be kept there and removed in th GitHub job using (must add key first in compsoer.json): composer config --unset repositories.powermail_pro - copy .project/tests/.php-cs-fixer.php from powermail repo (v12) - add php-cs-fixer as dev requiredment - copy .github/workflow/testing.yaml from powermail repo (v12) - use .build instead of .Build in scripts (since that is what is being used, also corresponds to powermail) - add phpstan, copy config from powermail - add "fix:php:cs" for fixing cgl - fix some phpstan warnings - add files for testing to .gitattributes (export-ignore) --- .editorconfig | 53 +++++++++ .gitattributes | 4 + .github/workflows/testing.yaml | 101 +++++++++++++++++ .project/tests/.php-cs-fixer.php | 111 +++++++++++++++++++ .project/tests/phpstan-baseline.neon | 6 + .project/tests/phpstan.neon | 14 +++ Classes/Command/CleanupCommand.php | 3 +- Classes/Command/ForceCleanupCommand.php | 1 + Classes/Command/InformReceiversCommand.php | 5 +- Classes/Controller/ModuleController.php | 6 +- Classes/Domain/Repository/MailRepository.php | 2 +- Classes/Service/TimeCalculationService.php | 5 +- Classes/Utility/FileUtility.php | 1 + composer.json | 15 ++- 14 files changed, 307 insertions(+), 20 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/testing.yaml create mode 100644 .project/tests/.php-cs-fixer.php create mode 100644 .project/tests/phpstan-baseline.neon create mode 100644 .project/tests/phpstan.neon diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3cf33e9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,53 @@ +# Unix-style newlines with a newline ending every file +# copied from in2code/powermail +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# TS/JS-Files +[*.{ts,js}] +indent_size = 2 + +# composer.json +# composer.json currently deviates from default by using 2 spaces indents +[composer.json] +indent_size = 2 + +# JSON-Files +[*.json] +indent_style = tab + +# ReST-Files (TYPO3 core convention is no longer 3 spaces, it is 4 spaces) +[*.{rst,rst.txt}] +indent_size = 4 +max_line_length = 80 + +# YAML-Files +[*.{yaml,yml}] +indent_size = 2 + +# package.json +# .travis.yml +[{package.json,.travis.yml}] +indent_size = 2 + +# TypoScript +[*.{typoscript,tsconfig}] +indent_size = 2 + +# XLF-Files +[*.xlf] +indent_style = tab + +# SQL-Files +[*.sql] +indent_style = tab +indent_size = 2 + +# .htaccess +[{_.htaccess,.htaccess}] +indent_style = tab diff --git a/.gitattributes b/.gitattributes index c9a6185..112f5cf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,5 @@ *.gz filter=lfs diff=lfs merge=lfs -text +/.editorconfig export-ignore +/.github export-ignore +/.project export-ignore +/Tests export-ignore diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml new file mode 100644 index 0000000..6cde97a --- /dev/null +++ b/.github/workflows/testing.yaml @@ -0,0 +1,101 @@ +# currently only testing with v12 and supported PHP versions for v12 (8.1-8.4) +# todo +# - execute "composer fix:php:cs" and uncomment "php-cs-fixer" job +name: testing +on: + push: + branches-ignore: + - 'l10n_*' + pull_request: + branches-ignore: + - 'l10n_*' + +jobs: + php-lint: + name: "PHP linter" + runs-on: ubuntu-24.04 + steps: + - name: "Checkout" + uses: actions/checkout@v4 + - name: "Install PHP" + uses: shivammathur/setup-php@v2 + with: + php-version: "${{ matrix.php-version }}" + coverage: none + tools: composer:v2 + - name: "Run PHP lint" + run: "composer test:php:lint" + strategy: + fail-fast: false + matrix: + php-version: + - 8.1 + - 8.2 + - 8.3 + - 8.4 + typoscript-lint: + name: "TypoScript linter" + runs-on: ubuntu-24.04 + steps: + - name: "Checkout" + uses: actions/checkout@v4 + - name: "Run TypoScript lint" + uses: TYPO3-Continuous-Integration/TYPO3-CI-Typoscript-Lint@v1 + with: + files: "./Configuration" + config_file: ".project/tests/typoscript-lint.yml" + #php-cs-fixer: + # name: "PHP CS Fixer" + # runs-on: ubuntu-24.04 + # needs: php-lint + # steps: + # - name: "Checkout" + # uses: actions/checkout@v4 + # - name: "Install PHP" + # uses: shivammathur/setup-php@v2 + # with: + # php-version: 8.1 + # - name: "Composer Install" + # run: "composer install" + # - name: "Run PHP CS Fixer" + # run: "composer test:php:cs" + phpstan: + name: "PHPstan" + runs-on: ubuntu-24.04 + needs: php-lint + steps: + - name: "Checkout" + uses: actions/checkout@v4 + - name: "Install PHP" + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + - name: "Composer Install" + run: "composer install" + - name: "Run PHPstan" + run: "composer test:php:phpstan" + #unit-tests: + # name: "PHP Unit Tests" + # runs-on: ubuntu-24.04 + # needs: php-lint + # steps: + # - name: Checkout + # uses: actions/checkout@v4 + # - name: "Install PHP" + # uses: shivammathur/setup-php@v2 + # with: + # php-version: "${{ matrix.php-version }}" + # coverage: none + # tools: composer:v2 + # - name: "Composer Install" + # run: "composer install" + # - name: "Run Unit Tests" + # run: "composer test:unit" + strategy: + fail-fast: false + matrix: + php-version: + - 8.1 + - 8.2 + - 8.3 + - 8.4 diff --git a/.project/tests/.php-cs-fixer.php b/.project/tests/.php-cs-fixer.php new file mode 100644 index 0000000..e2c1e18 --- /dev/null +++ b/.project/tests/.php-cs-fixer.php @@ -0,0 +1,111 @@ +in( + [ + __DIR__ . '/../../Classes', + __DIR__ . '/../../Tests', + __DIR__ . '/../../Configuration', + ] + ); +// Return a Code Sniffing configuration using +// all sniffers needed for PSR-2 +// and additionally: +// - Remove leading slashes in use clauses. +// - PHP single-line arrays should not have trailing comma. +// - Single-line whitespace before closing semicolon are prohibited. +// - Remove unused use statements in the PHP source code +// - Ensure Concatenation to have at least one whitespace around +// - Remove trailing whitespace at the end of blank lines. + +$config = new PhpCsFixer\Config(); + +return $config + ->setRiskyAllowed(true) + ->setRules([ + '@DoctrineAnnotation' => true, + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'blank_line_after_opening_tag' => true, + 'braces' => ['allow_single_line_closure' => true], + 'cast_spaces' => ['space' => 'none'], + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'dir_constant' => true, + 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']], + 'function_typehint_space' => true, + 'lowercase_cast' => true, + 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], + 'modernize_strpos' => false, // different to https://github.com/TYPO3/typo3/blob/main/Build/php-cs-fixer.php + 'modernize_types_casting' => true, + 'native_function_casing' => true, + 'new_with_braces' => 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_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_null_property_initialization' => false, // different to https://github.com/TYPO3/typo3/blob/main/Build/php-cs-fixer.php + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_superfluous_elseif' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_whitespace_in_blank_line' => true, + 'ordered_imports' => true, + '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' => false, // different to https://github.com/TYPO3/typo3/blob/main/Build/php-cs-fixer.php + '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_line_comment_style' => ['comment_types' => ['hash']], + 'single_trait_insert_per_statement' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arrays']], + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], + ])->setFinder($finder); diff --git a/.project/tests/phpstan-baseline.neon b/.project/tests/phpstan-baseline.neon new file mode 100644 index 0000000..b3eda86 --- /dev/null +++ b/.project/tests/phpstan-baseline.neon @@ -0,0 +1,6 @@ +parameters: + ignoreErrors: + - + message: "#^Static method In2code\\\\PowermailCleaner\\\\Service\\\\TimeCalculationService\\:\\:getTodaysStart\\(\\) is unused\\.$#" + count: 1 + path: ../../Classes/Service/TimeCalculationService.php diff --git a/.project/tests/phpstan.neon b/.project/tests/phpstan.neon new file mode 100644 index 0000000..1daf4e9 --- /dev/null +++ b/.project/tests/phpstan.neon @@ -0,0 +1,14 @@ +# tests for v12 +# todo +# - some phpstan tests will fail due to classes being XCLASSed and the code using the original class, can be explicitly +# defined using @var, see Command/CleanupCommand.php +includes: + - phpstan-baseline.neon +parameters: + level: 5 + tmpDir: ../../.build/var/cache/phpstan + paths: + - ../../Classes + scanDirectories: + - ../../.build/vendor/in2code/powermail + - ../../.build/vendor/typo3 diff --git a/Classes/Command/CleanupCommand.php b/Classes/Command/CleanupCommand.php index 5966ca0..1418409 100644 --- a/Classes/Command/CleanupCommand.php +++ b/Classes/Command/CleanupCommand.php @@ -25,6 +25,7 @@ protected function configure(): void } protected function execute(InputInterface $input, OutputInterface $output): int { + /** @var \In2code\PowermailCleaner\Domain\Repository\MailRepository $mailRepository */ $mailRepository = GeneralUtility::makeInstance(MailRepository::class); $mailsToDelete = $mailRepository->findAllDeletionTimeStampOlderThan(time()); $mails = 0; @@ -36,4 +37,4 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->logger->info('Removed mails: ' . $mails); return Command::SUCCESS; } -} \ No newline at end of file +} diff --git a/Classes/Command/ForceCleanupCommand.php b/Classes/Command/ForceCleanupCommand.php index 84b0d53..0c4243f 100644 --- a/Classes/Command/ForceCleanupCommand.php +++ b/Classes/Command/ForceCleanupCommand.php @@ -32,6 +32,7 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { + /** @var \In2code\PowermailCleaner\Domain\Repository\MailRepository $mailRepository */ $mailRepository = GeneralUtility::makeInstance(MailRepository::class); // ToDo: calculate timestamp $timestamp = (time() - $input->getArgument('Retention days') * 86400); diff --git a/Classes/Command/InformReceiversCommand.php b/Classes/Command/InformReceiversCommand.php index 1d43d2e..d6395a4 100644 --- a/Classes/Command/InformReceiversCommand.php +++ b/Classes/Command/InformReceiversCommand.php @@ -41,11 +41,8 @@ public function __construct( ) { parent::__construct(); $this->powermailCleanerTyposcript = $this->getTypoScriptConfiguration(); - /** @var MailRepository $mailRepository */ $this->mailRepository = GeneralUtility::makeInstance(MailRepository::class); - /** @var FlexFormService $flexFormService */ $this->flexFormService = GeneralUtility::makeInstance(FlexFormService::class); - /** @var Mail $mail */ $this->mail = GeneralUtility::makeInstance(Mail::class); $this->timeCalculationService = GeneralUtility::makeInstance(TimeCalculationService::class); } @@ -119,7 +116,7 @@ private function getTypoScriptConfiguration(): array private function findReceivers(array $flexform): array { - /** @var ReceiverAddressService $receiverService */ + /** @var ReceiverAddressService $addressService */ $addressService = GeneralUtility::makeInstance(ReceiverAddressService::class, $this->mail, $flexform); return $addressService->getReceiverEmails(); } diff --git a/Classes/Controller/ModuleController.php b/Classes/Controller/ModuleController.php index 0f724e6..1a2b72b 100644 --- a/Classes/Controller/ModuleController.php +++ b/Classes/Controller/ModuleController.php @@ -12,15 +12,11 @@ */ class ModuleController extends \In2code\Powermail\Controller\ModuleController { - /** - * @param int $age - * @param int $pid - */ public function cleanupAction(): ResponseInterface { $age = null; $pid = null; - + if ($this->request->hasArgument('age')) { $age = $this->request->getArgument('age'); } diff --git a/Classes/Domain/Repository/MailRepository.php b/Classes/Domain/Repository/MailRepository.php index a8aee3a..30c74eb 100644 --- a/Classes/Domain/Repository/MailRepository.php +++ b/Classes/Domain/Repository/MailRepository.php @@ -155,7 +155,7 @@ public function findMailsOlderThan(int $timestamp): array /** * @param int $mailIdentifier - * @return QueryBuilder + * @return array * @throws Exception */ public function getAnswersWithFiles(int $mailIdentifier): array diff --git a/Classes/Service/TimeCalculationService.php b/Classes/Service/TimeCalculationService.php index 231c9e5..5e66985 100644 --- a/Classes/Service/TimeCalculationService.php +++ b/Classes/Service/TimeCalculationService.php @@ -15,8 +15,11 @@ public function calculateNotificationTimeframe(int $informReceiversBeforeDeletio return $notificationLimit; } + /** + * @todo Remove? Is not used + */ private static function getTodaysStart(): int { return strtotime('today', time()); } -} \ No newline at end of file +} diff --git a/Classes/Utility/FileUtility.php b/Classes/Utility/FileUtility.php index 0d5e2db..e963d4d 100644 --- a/Classes/Utility/FileUtility.php +++ b/Classes/Utility/FileUtility.php @@ -80,6 +80,7 @@ public static function hasSysfileReference(int $sysFileUid): bool public static function deleteFromFilesystem(string $identifier, ?ResourceStorage $storage): void { + $resourceBasePath = ''; if ($storage instanceof ResourceStorage) { $resourceBasePath = $storage->getConfiguration()['basePath']; } diff --git a/composer.json b/composer.json index 4463cea..01dfbc7 100644 --- a/composer.json +++ b/composer.json @@ -81,14 +81,10 @@ "friends-of-behat/mink-extension": "^2.7", "behat/mink-selenium2-driver": "^1.7", "friends-of-behat/mink-browserkit-driver": "^1.6", - "drevops/behat-screenshot": "^1.2" + "drevops/behat-screenshot": "^1.2", + "phpstan/phpstan": "^1.11.7", + "saschaegerer/phpstan-typo3": "^1.10.2" }, - "repositories": [ - { - "type": "git", - "url": "git@github.com:in2code-pro/powermail.git" - } - ], "autoload": { "psr-4": { "In2code\\PowermailCleaner\\": "Classes/" @@ -122,8 +118,11 @@ "test:behaviour": "behat --config Tests/Behavior/behat.ddev.yml", "test:behaviour:tag": "behat --config Tests/Behavior/behat.ddev.yml --tags", "test:behaviour:stop": "behat --config Tests/Behavior/behat.ddev.yml --stop-on-failure", - "test:php:cs": ".Build/bin/php-cs-fixer --version && .Build/bin/php-cs-fixer fix --dry-run --config=.project/tests/.php-cs-fixer.php --diff", + "test:php:cs": ".build/bin/php-cs-fixer --version && .build/bin/php-cs-fixer fix --dry-run --config=.project/tests/.php-cs-fixer.php --diff", + "fix:php:cs": ".build/bin/php-cs-fixer --version && .build/bin/php-cs-fixer fix --config=.project/tests/.php-cs-fixer.php --diff", "test:php:lint": "find *.php Classes Configuration Tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l", + "test:php:phpstan": "phpstan analyse -c .project/tests/phpstan.neon", + "test:php:phpstan:generate-baseline": "phpstan analyse -c .project/tests/phpstan.neon --generate-baseline .project/tests/phpstan-baseline.neon", "test:typoscript:lint": "typoscript-lint --config=.project/tests/typoscript-lint.yml", "test:unit": "phpunit -c phpunit.xml.dist" } From 4c4031e2c8ccdf930e0162d3270dc89d81ce91dd Mon Sep 17 00:00:00 2001 From: Sybille Peters Date: Sat, 5 Apr 2025 14:09:19 +0200 Subject: [PATCH 2/2] Uncomment typoscript-lint job --- .github/workflows/testing.yaml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 6cde97a..76f3d0f 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -1,6 +1,7 @@ # currently only testing with v12 and supported PHP versions for v12 (8.1-8.4) # todo # - execute "composer fix:php:cs" and uncomment "php-cs-fixer" job +# - fix TypoScript linter and uncomment jog name: testing on: push: @@ -33,17 +34,17 @@ jobs: - 8.2 - 8.3 - 8.4 - typoscript-lint: - name: "TypoScript linter" - runs-on: ubuntu-24.04 - steps: - - name: "Checkout" - uses: actions/checkout@v4 - - name: "Run TypoScript lint" - uses: TYPO3-Continuous-Integration/TYPO3-CI-Typoscript-Lint@v1 - with: - files: "./Configuration" - config_file: ".project/tests/typoscript-lint.yml" + #typoscript-lint: + # name: "TypoScript linter" + # runs-on: ubuntu-24.04 + # steps: + # - name: "Checkout" + # uses: actions/checkout@v4 + # - name: "Run TypoScript lint" + # uses: TYPO3-Continuous-Integration/TYPO3-CI-Typoscript-Lint@v1 + # with: + # files: "./Configuration" + # config_file: ".project/tests/typoscript-lint.yml" #php-cs-fixer: # name: "PHP CS Fixer" # runs-on: ubuntu-24.04