From 063b326d770241ea2fc6eac6e0b25c8522ba4fde Mon Sep 17 00:00:00 2001 From: Lamm Date: Mon, 3 Jun 2024 14:07:27 +0200 Subject: [PATCH 1/4] Support PHP 8.3, drops < PHP 8.1 support --- .github/workflows/tasks.yml | 4 +- .gitignore | 1 + Classes/Event/RenderedEvent.php | 5 +- .../InternalSsiRedirectMiddleware.php | 5 +- Classes/Utility/VersionUtility.php | 2 +- .../ViewHelpers/RenderIncludeViewHelper.php | 26 ++++----- Configuration/RequestMiddlewares.php | 6 +- composer.json | 56 +++++++++---------- ext_emconf.php | 4 +- grumphp.yml | 16 ++++++ phpstan-baseline.neon | 1 + phpstan.neon | 7 +++ rector.php | 42 ++++++++++++++ 13 files changed, 121 insertions(+), 54 deletions(-) create mode 100644 grumphp.yml create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon create mode 100644 rector.php diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml index ec17e3c..49c1c03 100644 --- a/.github/workflows/tasks.yml +++ b/.github/workflows/tasks.yml @@ -7,7 +7,7 @@ jobs: name: Linting php with grumphp runs-on: ubuntu-latest container: - image: kanti/buildy:7.4 + image: kanti/buildy:8.1 steps: - uses: actions/checkout@v2 - uses: actions/cache@v2 @@ -40,7 +40,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' + php-version: '8.1' extensions: intl, mbstring, xml, soap, zip, curl tools: composer diff --git a/.gitignore b/.gitignore index 42c24f1..756ae3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ composer.lock public/ vendor/ +var/ diff --git a/Classes/Event/RenderedEvent.php b/Classes/Event/RenderedEvent.php index 222342d..ec522dc 100644 --- a/Classes/Event/RenderedEvent.php +++ b/Classes/Event/RenderedEvent.php @@ -6,11 +6,8 @@ class RenderedEvent { - protected string $html; - - public function __construct(string $html) + public function __construct(protected string $html) { - $this->html = $html; } public function getHtml(): string diff --git a/Classes/Middleware/InternalSsiRedirectMiddleware.php b/Classes/Middleware/InternalSsiRedirectMiddleware.php index a78f031..858bf34 100644 --- a/Classes/Middleware/InternalSsiRedirectMiddleware.php +++ b/Classes/Middleware/InternalSsiRedirectMiddleware.php @@ -18,17 +18,20 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface { if (isset($request->getQueryParams()['ssi_include'])) { $ssiInclude = $request->getQueryParams()['ssi_include']; - if (!preg_match('/^([a-zA-Z0-9_]+)$/', $ssiInclude)) { + if (!preg_match('/^(\w+)$/', (string) $ssiInclude)) { return new HtmlResponse('ssi_include invalid', 400); } + $cacheFileName = RenderIncludeViewHelper::SSI_INCLUDE_DIR . $ssiInclude; $absolutePath = Environment::getPublicPath() . $cacheFileName; if (!file_exists($absolutePath)) { // ignore response use the content of the file: $handler->handle($request->withAttribute('noCache', true)); } + return new HtmlResponse(file_get_contents($absolutePath) ?: ''); } + return $handler->handle($request); } } diff --git a/Classes/Utility/VersionUtility.php b/Classes/Utility/VersionUtility.php index 056a16e..2d967dd 100644 --- a/Classes/Utility/VersionUtility.php +++ b/Classes/Utility/VersionUtility.php @@ -18,7 +18,7 @@ public static function getVersion(): string $str = 'dev'; try { return explode('@', Versions::getVersion('andersundsehr/ssi-include'))[0] ?? $str; - } catch (Throwable $e) { + } catch (Throwable) { return $str; } } diff --git a/Classes/ViewHelpers/RenderIncludeViewHelper.php b/Classes/ViewHelpers/RenderIncludeViewHelper.php index 1853510..9daca3d 100644 --- a/Classes/ViewHelpers/RenderIncludeViewHelper.php +++ b/Classes/ViewHelpers/RenderIncludeViewHelper.php @@ -4,6 +4,8 @@ namespace AUS\SsiInclude\ViewHelpers; +use Webimpress\SafeWriter\Exception\ExceptionInterface; +use Closure; use AUS\SsiInclude\Event\RenderedEvent; use Exception; use TYPO3\CMS\Core\Context\Context; @@ -33,14 +35,12 @@ public function initializeArguments(): void /** * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * @return string - * @throws \Webimpress\SafeWriter\Exception\ExceptionInterface + * @throws Exception + * @throws ExceptionInterface */ - public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string + public static function renderStatic(array $arguments, Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string { - $name = static::validateName($arguments); + $name = self::validateName($arguments); $filename = static::getSiteName() . '_' . static::getLangauge() . '_' . $name; $basePath = self::SSI_INCLUDE_DIR . $filename; @@ -56,10 +56,11 @@ public static function renderStatic(array $arguments, \Closure $renderChildrenCl $eventDispatcher->dispatch($renderedHtmlEvent); $html = $renderedHtmlEvent->getHtml(); - @mkdir(dirname($absolutePath), octdec($GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']), true); + @mkdir(dirname($absolutePath), (int)octdec((string)$GLOBALS['TYPO3_CONF_VARS']['SYS']['folderCreateMask']), true); FileWriter::writeFile($absolutePath, $html); GeneralUtility::fixPermissions($absolutePath); } + return ''; } @@ -68,25 +69,24 @@ private static function shouldRenderFile(string $absolutePath, int $cacheLifeTim if (!file_exists($absolutePath)) { return true; } + if ((filemtime($absolutePath) + $cacheLifeTime) < time()) { return true; } - if (self::isBackendUser()) { - return true; - } - return false; + + return self::isBackendUser(); } /** * @param array $arguments - * @return string * @throws Exception */ private static function validateName(array $arguments): string { - if (ctype_alnum($arguments['name'])) { + if (ctype_alnum((string) $arguments['name'])) { return $arguments['name']; } + throw new Exception(sprintf('Only Alphanumeric characters allowed got: "%s"', $arguments['name'])); } diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php index cfa41fe..f503e75 100644 --- a/Configuration/RequestMiddlewares.php +++ b/Configuration/RequestMiddlewares.php @@ -1,9 +1,11 @@ [ - \AUS\SsiInclude\Middleware\InternalSsiRedirectMiddleware::class => [ - 'target' => \AUS\SsiInclude\Middleware\InternalSsiRedirectMiddleware::class, + InternalSsiRedirectMiddleware::class => [ + 'target' => InternalSsiRedirectMiddleware::class, 'before' => [ 'typo3/cms-core/normalized-params-attribute' ], diff --git a/composer.json b/composer.json index c337fb7..e6a0b66 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "name": "andersundsehr/ssi-include", "description": "Allows to periodically create ssi includes from anders und sehr GmbH", - "type": "typo3-cms-extension", "license": "GPL-3.0-or-later", + "type": "typo3-cms-extension", "authors": [ { "name": "Matthias Vogel", @@ -10,48 +10,44 @@ "homepage": "https://andersundsehr.com" } ], + "require": { + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "ocramius/package-versions": "^2.1.0", + "typo3/cms-fluid": "^10.4.0 || ^11.5.0 || ^12.4.0", + "typo3/cms-frontend": "^10.4.0 || ^11.5.0 || ^12.4.0", + "webimpress/safe-writer": "^2.2.0" + }, + "require-dev": { + "composer/composer": "^2.5.5", + "pluswerk/grumphp-config": "^7.0", + "saschaegerer/phpstan-typo3": "^1.10.0", + "ssch/typo3-rector": "^2.5.0" + }, "replace": { "typo3-ter/ssi-include": "self.version" }, - "extra": { - "typo3/cms": { - "extension-key": "ssi_include" - }, - "pluswerk/grumphp-config": { - "auto-setting": true - }, - "grumphp": { - "config-default-path": "vendor/pluswerk/grumphp-config/grumphp.yml" + "autoload": { + "psr-4": { + "AUS\\SsiInclude\\": "Classes/" } }, "config": { - "sort-packages": true, "allow-plugins": { + "ergebnis/composer-normalize": true, "phpro/grumphp": true, - "typo3/class-alias-loader": true, - "typo3/cms-composer-installers": true, + "phpstan/extension-installer": true, "pluswerk/grumphp-config": true, - "phpstan/extension-installer": true - } + "typo3/class-alias-loader": true, + "typo3/cms-composer-installers": true + }, + "sort-packages": true }, - "autoload": { - "psr-4": { - "AUS\\SsiInclude\\": "Classes/" + "extra": { + "typo3/cms": { + "extension-key": "ssi_include" } }, "ter-require": { "webimpress/safe-writer": "^2.2.0" - }, - "require": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", - "ocramius/package-versions": "^2.1.0", - "typo3/cms-fluid": "^10.4.0 || ^11.5.0 || ^12.4.0", - "typo3/cms-frontend": "^10.4.0 || ^11.5.0 || ^12.4.0", - "webimpress/safe-writer": "^2.2.0" - }, - "require-dev": { - "phpstan/extension-installer": "^1.1.0", - "pluswerk/grumphp-config": "^5.0", - "saschaegerer/phpstan-typo3": "^0.13.3" } } diff --git a/ext_emconf.php b/ext_emconf.php index f995f6f..d5190fc 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -1,5 +1,7 @@ 'SSI Include - Render your includes', @@ -10,7 +12,7 @@ 'author_company' => 'anders und sehr GmbH', 'state' => 'stable', 'clearCacheOnLoad' => 0, - 'version' => \AUS\SsiInclude\Utility\VersionUtility::getVersion(), + 'version' => VersionUtility::getVersion(), 'constraints' => [ 'depends' => [ 'typo3' => '10.4.0-11.99.99', diff --git a/grumphp.yml b/grumphp.yml new file mode 100644 index 0000000..3a60a5a --- /dev/null +++ b/grumphp.yml @@ -0,0 +1,16 @@ +imports: + - { resource: vendor/pluswerk/grumphp-config/grumphp.yml } +parameters: + convention.process_timeout: 240 + convention.security_checker_blocking: true + convention.jsonlint_ignore_pattern: { } + convention.xmllint_ignore_pattern: { } + convention.yamllint_ignore_pattern: { } + convention.phpcslint_ignore_pattern: { } + convention.phpcslint_exclude: { } + convention.xlifflint_ignore_pattern: { } + convention.rector_ignore_pattern: { } + convention.rector_enabled: true + convention.rector_config: rector.php + convention.rector_clear-cache: false + convention.phpstan_level: null diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..9631d44 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1 @@ +parameters: diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..e178ba6 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,7 @@ +includes: + - phpstan-baseline.neon + - vendor/andersundsehr/phpstan-git-files/extension.php + +parameters: + level: 8 + reportUnmatchedIgnoredErrors: false diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..0f267f7 --- /dev/null +++ b/rector.php @@ -0,0 +1,42 @@ +parallel(); + $rectorConfig->importNames(); + $rectorConfig->importShortClasses(); + $rectorConfig->cacheClass(FileCacheStorage::class); + $rectorConfig->cacheDirectory('./var/cache/rector'); + + $rectorConfig->paths( + array_filter(explode("\n", (string)shell_exec("git ls-files | xargs ls -d 2>/dev/null | grep -E '\.(php)$'"))) + ); + + // define sets of rules + $rectorConfig->sets( + [ + ...RectorSettings::sets(true), + ...RectorSettings::setsTypo3(false), + ] + ); + + // remove some rules + // ignore some files + $rectorConfig->skip( + [ + ...RectorSettings::skip(), + ...RectorSettings::skipTypo3(), + + /** + * rector should not touch these files + */ + //__DIR__ . '/src/Example', + //__DIR__ . '/src/Example.php', + ] + ); +}; From 4fbff636cda7cc4229751ec5278ebebd0d4d3caa Mon Sep 17 00:00:00 2001 From: Lamm Date: Mon, 3 Jun 2024 14:37:12 +0200 Subject: [PATCH 2/4] Fix github tasks --- .github/workflows/tasks.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml index 49c1c03..e70e3cf 100644 --- a/.github/workflows/tasks.yml +++ b/.github/workflows/tasks.yml @@ -4,19 +4,30 @@ on: [push, pull_request] jobs: lint-php: - name: Linting php with grumphp + name: "php: ${{ matrix.php }} TYPO3: ${{ matrix.typo3 }}" runs-on: ubuntu-latest - container: - image: kanti/buildy:8.1 + strategy: + fail-fast: false + matrix: + php: [ '8.1', '8.2', '8.3' ] + typo3: [ '11', '12', '13' ] + exclude: + - php: '8.1' + typo3: '13' steps: + - name: Setup PHP with PECL extension + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} - uses: actions/checkout@v2 - uses: actions/cache@v2 with: path: ~/.composer/cache/files - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }} restore-keys: | - ${{ runner.os }}-composer- - - run: composer install --no-interaction --no-progress --ignore-platform-req=ext* + ${{ runner.os }}-${{ matrix.php }}-composer- + - run: composer require typo3/minimal="^${{ matrix.typo3 }}" -W --dev + - run: composer install --no-interaction --no-progress - run: ./vendor/bin/grumphp run --ansi ter-release: From dfd6b393abf294d0bb4c98cb9bd01f86cdad0b95 Mon Sep 17 00:00:00 2001 From: Lamm Date: Mon, 3 Jun 2024 14:47:15 +0200 Subject: [PATCH 3/4] Fixup drop v13 support from tests --- .github/workflows/tasks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml index e70e3cf..fcdc2c2 100644 --- a/.github/workflows/tasks.yml +++ b/.github/workflows/tasks.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: php: [ '8.1', '8.2', '8.3' ] - typo3: [ '11', '12', '13' ] + typo3: [ '11', '12' ] exclude: - php: '8.1' typo3: '13' From b462b1818869d55a4a1f2ba601221d2749479b63 Mon Sep 17 00:00:00 2001 From: Lamm Date: Thu, 13 Jun 2024 10:35:28 +0200 Subject: [PATCH 4/4] Clear SSI files if all or (all) pages cache clear triggers --- Classes/Cache/ClearCache.php | 39 ++++++++++++++++++++++++++++++++++++ ext_localconf.php | 4 ++++ 2 files changed, 43 insertions(+) create mode 100644 Classes/Cache/ClearCache.php diff --git a/Classes/Cache/ClearCache.php b/Classes/Cache/ClearCache.php new file mode 100644 index 0000000..84cc4f7 --- /dev/null +++ b/Classes/Cache/ClearCache.php @@ -0,0 +1,39 @@ + $parameters */ + public function clearCache(array $parameters): void + { + if (isset($parameters['cacheCmd']) && ($parameters['cacheCmd'] === 'pages' || $parameters['cacheCmd'] === 'all')) { + $path = Environment::getPublicPath() . RenderIncludeViewHelper::SSI_INCLUDE_DIR; + $this->removeFiles($path); + } + } + + protected function removeFiles(string $dir): void + { + if (is_dir($dir)) { + $objects = scandir($dir); + if (!$objects) { + return; + } + + foreach ($objects as $object) { + if ($object !== '.' && $object !== '..') { + $filePath = $dir . DIRECTORY_SEPARATOR . $object; + if (is_file($filePath) && is_writable($filePath)) { + unlink($filePath); + } + } + } + } + } +} diff --git a/ext_localconf.php b/ext_localconf.php index 82517ea..ca4e54f 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,6 +1,10 @@ clearCache';