From 5e0e884ca1c8c2ff920e1abd879e0bb901f7d47c Mon Sep 17 00:00:00 2001 From: Tim Weisenberger Date: Mon, 29 Jan 2024 09:20:29 +0100 Subject: [PATCH 1/2] feat: Update extension to TYPO3 v12 --- .editorconfig | 60 +++++++ .github/dependabot.yml | 11 ++ .github/workflows/apply-coding-standard.yml | 70 ++++++++ .github/workflows/ci.yml | 142 ++++++--------- Classes/EventListener/AddCdnToResource.php | 32 ++-- .../AddFileCacheTagForTypolink.php | 45 +++++ .../EventListener/FlushCacheTagForFile.php | 5 +- Classes/SignalSlot/ResourceStorage.php | 34 ---- Configuration/Services.yaml | 31 ++-- LICENSE.txt | 21 +++ Makefile | 11 +- Readme.md => README.md | 5 +- composer.json | 101 ++++++----- ecs.php | 27 +++ ext_emconf.php | 21 --- ext_localconf.php | 8 - phpunit.xml | 38 ++-- phpunit_functional.xml | 46 ++--- rector.php | 167 ++++++++++++++++++ 19 files changed, 603 insertions(+), 272 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/apply-coding-standard.yml create mode 100644 Classes/EventListener/AddFileCacheTagForTypolink.php delete mode 100644 Classes/SignalSlot/ResourceStorage.php create mode 100644 LICENSE.txt rename Readme.md => README.md (73%) create mode 100644 ecs.php delete mode 100644 ext_emconf.php delete mode 100755 ext_localconf.php create mode 100644 rector.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..379a529 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,60 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +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 + +# JSON-Files +[*.json] +indent_style = tab + +# ReST-Files +[*.{rst,rst.txt}] +indent_size = 4 +max_line_length = 80 + +# Markdown-Files +[*.md] +max_line_length = 80 + +# YAML-Files +[*.{yaml,yml}] +indent_size = 2 + +# NEON-Files +[*.neon] +indent_size = 2 +indent_style = tab + +# package.json +[package.json] +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 \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..c783a40 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: composer + directory: / + schedule: + interval: daily \ No newline at end of file diff --git a/.github/workflows/apply-coding-standard.yml b/.github/workflows/apply-coding-standard.yml new file mode 100644 index 0000000..3734752 --- /dev/null +++ b/.github/workflows/apply-coding-standard.yml @@ -0,0 +1,70 @@ +name: Apply Coding Standard + +on: + push: + branches: + - main + +jobs: + php-coding-standard: + name: 'Apply PHP Coding Standard' + runs-on: ubuntu-latest + steps: + - name: 'Checkout Code' + uses: actions/checkout@v4 + + - name: 'Setup PHP' + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: composer + + - name: 'Get Composer Cache Directory' + id: composer-cache + shell: bash + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: 'Cache Composer Dependencies' + uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: composer + + - name: 'Install Composer Dependencies' + shell: bash + run: composer install --no-interaction + + - name: 'Rector PHP Code' + shell: bash + run: composer rector-fix + + - name: 'Lint PHP Code' + shell: bash + run: composer lint-fix + + - name: 'Run PHPUnit unit tests' + shell: bash + run: composer test-unit + + - name: 'Run PHPUnit functional tests' + shell: bash + run: composer test-functional + + - name: 'Create pull-request' + id: cpr + uses: peter-evans/create-pull-request@v5.0.2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "[automated] Apply Coding Standard" + base: 'main' + branch: 'automated-apply-coding-standards' + title: '[automated] Apply Coding Standard' + labels: 'automated' + delete-branch: true + + - name: 'Enable Pull Request Merge when ready' + if: steps.cpr.outputs.pull-request-operation == 'created' + run: gh pr merge --auto "${{ steps.cpr.outputs.pull-request-number }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e74cffc..da1049c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,17 @@ name: Test TYPO3 Extension -on: [ push, pull_request ] +# Make sure only one build is running per branch at a time +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + push: + branches: + - main + pull_request: + branches: + - main permissions: contents: read @@ -8,120 +19,75 @@ permissions: jobs: test: - - runs-on: ubuntu-22.04 - - name: TYPO3 ${{ matrix.typo3}} on PHP ${{ matrix.php }} + runs-on: ubuntu-latest + name: TYPO3 v12.4 tests on PHP ${{ matrix.php }} strategy: fail-fast: false matrix: - php: [ 7.4, 8.0, 8.1 ] - typo3: [ 10.4, 11.5 ] - - exclude: - # do not run TYPO3 10.4 on PHP 8 - - php: 8.0 - typo3: 10.4 - # do not run TYPO3 10.4 on PHP 8.1 - - php: 8.1 - typo3: 10.4 + php: [ 8.1, 8.2, 8.3 ] steps: - - name: Checkout - uses: actions/checkout@v3 + - name: 'Checkout code' + uses: actions/checkout@v4 - - name: Setup PHP + - name: 'Setup PHP' uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} tools: composer + coverage: 'xdebug3' extensions: pdo, sqlite3 - - name: Validate composer.json and composer.lock - run: composer validate --strict - - - name: Get Composer Cache Directory + - name: 'Get Composer Cache Directory' id: composer-cache + shell: bash run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" - - uses: actions/cache@v3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: composer-php${{ matrix.php }}-typo3${{ matrix.typo3 }} - - - name: Install TYPO3 core - run: composer require typo3/cms-core="^${{ matrix.typo3 }}" -W - - - name: Unit Tests - run: .Build/bin/phpunit -c phpunit.xml + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Functional Tests - run: .Build/bin/phpunit -c phpunit_functional.xml - - # upload results for later use - - uses: actions/upload-artifact@master - if: github.event_name == 'pull_request' + - name: 'Cache Composer Dependencies' + uses: actions/cache@v3 with: - name: coverage-results - path: .Build/logs/coverage/ - - - report: - # only run on pull request - if: github.event_name == 'pull_request' + path: ${{ steps.composer-cache.outputs.dir }} + key: composer-php${{ matrix.php }} - runs-on: ubuntu-22.04 + - name: 'Validate composer.json and composer.lock' + shell: bash + run: composer validate --strict - name: Create Test Result Report + - name: 'Install Composer Dependencies' + shell: bash + run: composer install --no-interaction - needs: [ test ] + - name: 'PHPUnit unit tests' + shell: bash + run: composer test-unit - steps: - - name: Checkout - uses: actions/checkout@v3 + - name: 'PHPUnit functional tests' + shell: bash + run: composer test-functional - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - # soyhuce/phpunit-to-cobertura is not compatible with with PHP > 7.4 yet - php-version: 7.4 - tools: composer - extensions: pdo, sqlite3 + - name: 'Merge Coverage Reports' + shell: bash + run: .Build/bin/phpcov merge --html .Build/artifacts/coverage/merged --clover .Build/artifacts/coverage/clover.xml .Build/artifacts/coverage/ - - uses: actions/download-artifact@master + - name: 'Generate code coverage summary report' + uses: saschanowak/CloverCodeCoverageSummary@0.4.0 with: - name: coverage-results - path: .Build/logs/coverage/ - - - name: Install Dependencies - run: composer install --no-interaction + filename: .Build/artifacts/coverage/clover.xml - # merge result files from unit tests and functional tests - - name: Merge Coverage Reports - run: .Build/bin/phpcov merge --php .Build/logs/coverage.php .Build/logs/coverage/ + - name: 'Add code coverage summary as action run comment' + run: | + cat code-coverage-summary.md >> $GITHUB_STEP_SUMMARY + cat code-coverage-details.md >> $GITHUB_STEP_SUMMARY - # convert result file to cobertura - - name: Generate Cobertura Report - run: composer require soyhuce/phpunit-to-cobertura && .Build/bin/phpunit-to-cobertura .Build/logs/coverage.php .Build/logs/cobertura.xml + - name: 'Add title to code coverage summary' + shell: bash + run: sed -i '1 i\## TYPO3 v12.4 tests on PHP ${{ matrix.php }}' code-coverage-summary.md - # finally use the cobertura report and generate coverage summary - - name: Code Coverage Summary Report - uses: irongut/CodeCoverageSummary@v1.2.0 - with: - filename: .Build/logs/cobertura.xml - badge: true - # there are not enough tests yet - fail_below_min: false - format: markdown - hide_branch_rate: true - hide_complexity: false - indicators: true - output: both - thresholds: '60 80' - - - name: Add Coverage PR Comment + - name: 'Add code coverage summary as pr comment' uses: marocchino/sticky-pull-request-comment@v2 with: + header: coverage-${{ matrix.php }} recreate: true - path: code-coverage-results.md + path: code-coverage-summary.md \ No newline at end of file diff --git a/Classes/EventListener/AddCdnToResource.php b/Classes/EventListener/AddCdnToResource.php index 5122cae..2ca86f9 100644 --- a/Classes/EventListener/AddCdnToResource.php +++ b/Classes/EventListener/AddCdnToResource.php @@ -1,4 +1,5 @@ getDriver(); $resource = $event->getResource(); - if (! ($driver instanceof LocalDriver) || $environmentService->isEnvironmentInBackendMode()) { + if ( + !($driver instanceof LocalDriver) || + ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isBackend() + ) { return; } - if (($resource instanceof File || $resource instanceof ProcessedFile) && ($resource->getStorage( - )->getCapabilities( - ) & ResourceStorageInterface::CAPABILITY_PUBLIC) == ResourceStorageInterface::CAPABILITY_PUBLIC) { - $event->setPublicUrl($this->addCdnPrefixToUrl($resource, $driver)); + if (!$resource instanceof File && !$resource instanceof ProcessedFile) { + return; } + + if (($resource->getStorage()->getCapabilities( + ) & ResourceStorageInterface::CAPABILITY_PUBLIC) !== ResourceStorageInterface::CAPABILITY_PUBLIC) { + return; + } + + $event->setPublicUrl($this->addCdnPrefixToUrl($resource, $driver)); } private function addCdnPrefixToUrl(ResourceInterface $resourceObject, DriverInterface $driver): string { $publicUrl = $driver->getPublicUrl($resourceObject->getIdentifier()); $cdnBaseUrl = $this->getCdnBase(); - if (! $resourceObject instanceof ProcessedFile) { + if (!$resourceObject instanceof ProcessedFile) { $publicUrl = GeneralUtility::createVersionNumberedFilename($publicUrl); } - return (string) (new Uri($publicUrl))->withScheme('https')->withHost($cdnBaseUrl->getHost()); + + return (string) (new Uri($publicUrl))->withScheme('https') + ->withHost($cdnBaseUrl->getHost()); } private function getCdnBase(): UriInterface @@ -52,9 +61,10 @@ private function getCdnBase(): UriInterface $request = $this->getRequest(); $site = $request->getAttribute('site'); assert($site instanceof Site); + try { return new Uri($site->getAttribute('cdnBase')); - } catch (InvalidArgumentException $exception) { + } catch (InvalidArgumentException) { return $site->getBase(); } } diff --git a/Classes/EventListener/AddFileCacheTagForTypolink.php b/Classes/EventListener/AddFileCacheTagForTypolink.php new file mode 100644 index 0000000..0332a98 --- /dev/null +++ b/Classes/EventListener/AddFileCacheTagForTypolink.php @@ -0,0 +1,45 @@ +getLinkResult()->getType() !== 'file') { + return; + } + + if (!array_key_exists('href', $event->getContentObjectRenderer()->parameters)) { + return; + } + + $linkService = GeneralUtility::makeInstance(LinkService::class); + $resolvedLink = $linkService->resolveByStringRepresentation( + $event->getContentObjectRenderer()->parameters['href'] + ); + + if (!array_key_exists('file', $resolvedLink)) { + return; + } + + /** @var FileInterface $file */ + $file = $resolvedLink['file']; + + $this->getTypoScriptFrontendController() + ->addCacheTags(['sys_file_' . (int)$file->getProperty('uid')]); + } + + private function getTypoScriptFrontendController(): TypoScriptFrontendController + { + return $GLOBALS['TSFE']; + } +} diff --git a/Classes/EventListener/FlushCacheTagForFile.php b/Classes/EventListener/FlushCacheTagForFile.php index 986a5b1..1c72e4c 100644 --- a/Classes/EventListener/FlushCacheTagForFile.php +++ b/Classes/EventListener/FlushCacheTagForFile.php @@ -1,4 +1,5 @@ flushCacheByFile($event->getFile()); @@ -40,10 +40,9 @@ public function afterFileContentsSet(AfterFileContentsSetEvent $event): void $this->flushCacheByFile($event->getFile()); } - private function flushCacheByFile(FileInterface $file) + private function flushCacheByFile(FileInterface $file): void { $cacheManager = GeneralUtility::makeInstance(CacheManager::class); $cacheManager->flushCachesByTag('sys_file_' . (int) $file->getProperty('uid')); } - } diff --git a/Classes/SignalSlot/ResourceStorage.php b/Classes/SignalSlot/ResourceStorage.php deleted file mode 100644 index c2c9de3..0000000 --- a/Classes/SignalSlot/ResourceStorage.php +++ /dev/null @@ -1,34 +0,0 @@ -getTypoScriptFrontendController()->addCacheTags(['sys_file_' . (int) $file->getProperty('uid')]); - } - - private function getTypoScriptFrontendController(): TypoScriptFrontendController - { - return $GLOBALS['TSFE']; - } - -} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index a565e87..679a40b 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -3,36 +3,45 @@ services: autowire: true autoconfigure: true public: false + Netlogix\Nxsimplecdn\: resource: '../Classes/*' + Netlogix\Nxsimplecdn\EventListener\AddCdnToResource: tags: - name: event.listener - identifier: 'generatePublicUrlForResourceListener' + identifier: 'nxsimplecdn/generatePublicUrlForResourceListener' event: TYPO3\CMS\Core\Resource\Event\GeneratePublicUrlForResourceEvent + Netlogix\Nxsimplecdn\EventListener\FlushCacheTagForFile: tags: - - name: evnet.listener - identifier: 'flushCacheAfterFileContentsSet' + - name: event.listener + identifier: 'nxsimplecdn/flushCacheAfterFileContentsSet' method: 'afterFileContentsSet' event: TYPO3\CMS\Core\Resource\Event\AfterFileContentsSetEvent - - name: evnet.listener - identifier: 'flushCacheAfterFileDeleted' + - name: event.listener + identifier: 'nxsimplecdn/flushCacheAfterFileDeleted' method: 'afterFileDeleted' event: TYPO3\CMS\Core\Resource\Event\AfterFileDeletedEvent - - name: evnet.listener - identifier: 'flushCacheAfterFileMoved' + - name: event.listener + identifier: 'nxsimplecdn/flushCacheAfterFileMoved' method: 'afterFileMoved' event: TYPO3\CMS\Core\Resource\Event\AfterFileMovedEvent - - name: evnet.listener - identifier: 'flushCacheAfterFileRenamed' + - name: event.listener + identifier: 'nxsimplecdn/flushCacheAfterFileRenamed' method: 'afterFileRenamed' event: TYPO3\CMS\Core\Resource\Event\AfterFileRenamedEvent - - name: evnet.listener - identifier: 'flushCacheAfterFileReplaced' + - name: event.listener + identifier: 'nxsimplecdn/flushCacheAfterFileReplaced' method: 'afterFileReplaced' event: TYPO3\CMS\Core\Resource\Event\AfterFileReplacedEvent + + Netlogix\Nxsimplecdn\EventListener\AddFileCacheTagForTypolink: + tags: + - name: event.listener + identifier: 'nxsimplecdn/addFileCacheTagForTypolink' + event: TYPO3\CMS\Frontend\Event\AfterLinkIsGeneratedEvent diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..8c96b2f --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023-present netlogix GmbH & Co. KG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index c7a7029..b7f9c07 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,12 @@ clean: rm -rf .Build/ deps: - mkdir -p .Build/logs/coverage/ composer install update: composer update -W test: - XDEBUG_MODE=coverage,debug .Build/bin/phpunit -c phpunit.xml - XDEBUG_MODE=coverage,debug .Build/bin/phpunit -c phpunit_functional.xml - # merge and generate clover and html report - XDEBUG_MODE=coverage .Build/bin/phpunit-merger coverage .Build/logs/coverage/ --html=.Build/logs/html/ .Build/logs/clover.xml - # merge into php coverage - .Build/bin/phpcov merge --php .Build/logs/coverage.php .Build/logs/coverage/ - .Build/bin/phpunit-merger log .Build/logs/junit/ .Build/logs/junit.xml + XDEBUG_MODE=coverage .Build/bin/phpunit -c phpunit.xml + XDEBUG_MODE=coverage .Build/bin/phpunit -c phpunit_functional.xml + .Build/bin/phpcov merge --html .Build/artifacts/coverage/merged --clover .Build/artifacts/coverage/clover.xml .Build/artifacts/coverage/ diff --git a/Readme.md b/README.md similarity index 73% rename from Readme.md rename to README.md index 11b99cf..04bd1c8 100644 --- a/Readme.md +++ b/README.md @@ -1,9 +1,8 @@ # TYPO3 Extension nxsimplecdn [![stability-beta](https://img.shields.io/badge/stability-beta-33bbff.svg)](https://github.com/netlogix/nxsimplecdn) -[![TYPO3 V10](https://img.shields.io/badge/TYPO3-10-orange.svg)](https://get.typo3.org/version/10) -[![TYPO3 V11](https://img.shields.io/badge/TYPO3-11-orange.svg)](https://get.typo3.org/version/11) -[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.4-8892BF.svg)](https://php.net/) +[![TYPO3 V12](https://img.shields.io/badge/TYPO3-12-orange.svg)](https://get.typo3.org/version/12) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.1-8892BF.svg)](https://php.net/) [![GitHub CI status](https://github.com/netlogix/nxsimplecdn/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/netlogix/nxsimplecdn/actions) # Installation diff --git a/composer.json b/composer.json index d9abf1c..6c831dc 100644 --- a/composer.json +++ b/composer.json @@ -1,50 +1,55 @@ { - "name": "netlogix/nxsimplecdn", - "description": "Simple cdn extension for TYPO3", - "license": "MIT", - "type": "typo3-cms-extension", - "require": { - "php": "^7.4 || ^8.0 || ^8.1", - "typo3/cms-core": "^10.4 || ^11.5" - }, - "require-dev": { - "ext-sqlite3": "*", - "nimut/testing-framework": "^6.0", - "nimut/phpunit-merger": "^1.1", - "phpunit/phpcov": "^8.2" - }, - "autoload": { - "psr-4": { - "Netlogix\\Nxsimplecdn\\": "Classes/" - } - }, - "autoload-dev": { - "psr-4": { - "Netlogix\\Nxsimplecdn\\Tests\\": "Tests/" - } - }, - "extra": { - "typo3/cms": { - "extension-key": "nxsimplecdn", - "web-dir": ".Build/Web", - "cms-package-dir": "{$vendor-dir}/typo3/cms" - } - }, - "config": { - "vendor-dir": ".Build/vendor", - "bin-dir": ".Build/bin", - "allow-plugins": { - "typo3/cms-composer-installers": true, - "typo3/class-alias-loader": true - } - }, - "scripts": { - "post-autoload-dump": [ - "@prepare-extension-test-structure", - "mkdir -p .Build/logs/" - ], - "prepare-extension-test-structure": [ - "Nimut\\TestingFramework\\Composer\\ExtensionTestEnvironment::prepare" - ] - } + "name": "netlogix/nxsimplecdn", + "description": "Simple cdn extension for TYPO3", + "license": "MIT", + "type": "typo3-cms-extension", + "require": { + "php": "^8.1", + "typo3/cms-core": "^12.4" + }, + "require-dev": { + "ext-sqlite3": "*", + "ssch/typo3-rector": "^1.5", + "typo3/testing-framework": "^8.0", + "phpunit/phpcov": "^9.0", + "netlogix/coding-guidelines-php": "^1.0" + }, + "autoload": { + "psr-4": { + "Netlogix\\Nxsimplecdn\\": "Classes/" + } + }, + "autoload-dev": { + "psr-4": { + "Netlogix\\Nxsimplecdn\\Tests\\": "Tests/" + } + }, + "extra": { + "typo3/cms": { + "extension-key": "nxsimplecdn", + "web-dir": ".Build/public" + } + }, + "config": { + "vendor-dir": ".Build/vendor", + "bin-dir": ".Build/bin", + "allow-plugins": { + "typo3/cms-composer-installers": true, + "typo3/class-alias-loader": true + } + }, + "scripts": { + "rector": "rector process --dry-run", + "rector-fix": "rector process", + "lint": "ecs check", + "lint-fix": "ecs check --fix", + "test-unit": "phpunit -c phpunit.xml", + "test-functional": "phpunit -c phpunit_functional.xml", + "post-autoload-dump": [ + "@prepare-extension-test-structure" + ], + "prepare-extension-test-structure": [ + "Nimut\\TestingFramework\\Composer\\ExtensionTestEnvironment::prepare" + ] + } } diff --git a/ecs.php b/ecs.php new file mode 100644 index 0000000..acaa345 --- /dev/null +++ b/ecs.php @@ -0,0 +1,27 @@ +configure($ecsConfig); + + $ecsConfig->paths( + [ + __DIR__ . '/Classes', + __DIR__ . '/Configuration', + __DIR__ . '/Tests', + __DIR__ . '/ext_localconf.php', + ] + ); + + $ecsConfig->skip([ + DeclareStrictTypesFixer::class => [ + __DIR__ . '/ext_tables.php', + __DIR__ . '/Configuration/TCA/*', + ] + ]); +}; diff --git a/ext_emconf.php b/ext_emconf.php deleted file mode 100644 index dfd26d6..0000000 --- a/ext_emconf.php +++ /dev/null @@ -1,21 +0,0 @@ - 'netlogix simple CDN', - 'description' => 'Add cdn domain to all assets', - 'category' => 'fe', - 'author' => 'Sascha Nowak', - 'author_email' => 'sascha.nowak@netlogix.de', - 'author_company' => 'netlogix GmbH & Co. KG', - 'state' => 'stable', - 'version' => '1.0.0', - 'constraints' => [ - 'depends' => [ - 'typo3' => '10.4.0-11.5.99', - ], - 'conflicts' => [], - 'suggests' => [], - ], - '_md5_values_when_last_written' => '' -]; diff --git a/ext_localconf.php b/ext_localconf.php deleted file mode 100755 index 906e66b..0000000 --- a/ext_localconf.php +++ /dev/null @@ -1,8 +0,0 @@ -addFileCacheTagForTypolink'; - } -})(); diff --git a/phpunit.xml b/phpunit.xml index 7987773..4f417c8 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,17 +1,15 @@ @@ -20,19 +18,27 @@ - + - Classes + Classes + + - + + + - - + + + + + + diff --git a/phpunit_functional.xml b/phpunit_functional.xml index dfc3406..3e1f5ed 100644 --- a/phpunit_functional.xml +++ b/phpunit_functional.xml @@ -1,23 +1,16 @@ - - - - - @@ -25,18 +18,29 @@ - + - Classes + Classes + + - + + + - - + + + + + + + + + diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..2e8896c --- /dev/null +++ b/rector.php @@ -0,0 +1,167 @@ +parameters(); + // $parameters->set(Typo3Option::TYPOSCRIPT_INDENT_SIZE, 2); + + $rectorConfig->sets([ + // PHP + LevelSetList::UP_TO_PHP_81, + + SetList::CODE_QUALITY, + SetList::CODING_STYLE, + SetList::DEAD_CODE, + SetList::TYPE_DECLARATION, + SetList::EARLY_RETURN, + SetList::INSTANCEOF, + + // PhpUnit + PHPUnitLevelSetList::UP_TO_PHPUNIT_100, + + // TYPO3 + // v7 + Typo3SetList::TCA_76, + + // v8 + Typo3SetList::TCA_87, + + // v9 + Typo3SetList::TCA_95, + Typo3SetList::EXTBASE_COMMAND_CONTROLLERS_TO_SYMFONY_COMMANDS, + + // v10 + Typo3SetList::TCA_104, + Typo3SetList::TYPOSCRIPT_CONDITIONS_95, + Typo3SetList::TYPOSCRIPT_100, + Typo3SetList::TYPOSCRIPT_CONDITIONS_104, + Typo3SetList::DATABASE_TO_DBAL, + + // v11 + Typo3SetList::TCA_114, + Typo3SetList::REGISTER_ICONS_TO_ICON, + + // v12 + Typo3SetList::TCA_120, + Typo3SetList::TCA_123, + Typo3SetList::TYPOSCRIPT_120, + + // Typo3LevelSetList::UP_TO_TYPO3_7, + // Typo3LevelSetList::UP_TO_TYPO3_8, + // Typo3LevelSetList::UP_TO_TYPO3_9, + // Typo3LevelSetList::UP_TO_TYPO3_10, + // Typo3LevelSetList::UP_TO_TYPO3_11, + Typo3LevelSetList::UP_TO_TYPO3_12, + + NimutTestingFrameworkSetList::NIMUT_TESTING_FRAMEWORK_TO_TYPO3_TESTING_FRAMEWORK + ]); + + $rectorConfig->rule(SubstituteConstantsModeAndRequestTypeRector::class); + + // Define your target version which you want to support + $rectorConfig->phpVersion(PhpVersion::PHP_81); + + $parameters = $rectorConfig->parameters(); + $parameters->set(Option::IMPORT_SHORT_CLASSES, false); + $parameters->set(Option::AUTO_IMPORT_DOC_BLOCK_NAMES, false); + + // If you only want to process one/some TYPO3 extension(s), you can specify its path(s) here. + // If you use the option --config change __DIR__ to getcwd() + $rectorConfig->paths([ + __DIR__, + ]); + + // When you use rector there are rules that require some more actions like creating UpgradeWizards for outdated TCA types. + // To fully support you we added some warnings. So watch out for them. + + // If you use importNames(), you should consider excluding some TYPO3 files. + $rectorConfig->skip([ + // PHP + AddLiteralSeparatorToNumberRector::class, + UnSpreadOperatorRector::class => [ + __DIR__ . '/Classes/Service/LocationFactory.php', + ], + TypedPropertyFromStrictConstructorRector::class => [ + __DIR__ . '/Classes/Service/Importer.php', + ], + + // TYPO3 + // @see https://github.com/sabbelasichon/typo3-rector/issues/2536 + __DIR__ . '/**/Configuration/ExtensionBuilder/*', + // We skip those directories on purpose as there might be node_modules or similar + // that include typescript which would result in false positive processing + __DIR__ . '/**/Resources/**/node_modules/*', + __DIR__ . '/**/Resources/**/NodeModules/*', + __DIR__ . '/**/Resources/**/BowerComponents/*', + __DIR__ . '/**/Resources/**/bower_components/*', + __DIR__ . '/**/Resources/**/build/*', + __DIR__ . '/**/Resources/**/App/*', + __DIR__ . '/**/Resources/Public/*', + __DIR__ . '/vendor/*', + __DIR__ . '/Build/*', + __DIR__ . '/public/*', + __DIR__ . '/.github/*', + __DIR__ . '/.Build/*', + NameImportingPostRector::class => [ + 'ext_localconf.php', + 'ext_tables.php', + 'ClassAliasMap.php', + __DIR__ . '/**/Configuration/*.php', + __DIR__ . '/**/Configuration/**/*.php', + ] + ]); + + // If you have trouble that rector cannot run because some TYPO3 constants are not defined add an additional constants file + // @see https://github.com/sabbelasichon/typo3-rector/blob/master/typo3.constants.php + // @see https://github.com/rectorphp/rector/blob/main/docs/static_reflection_and_autoload.md#include-files + // $parameters->set(Option::BOOTSTRAP_FILES, [ + // __DIR__ . '/typo3.constants.php' + // ]); + + // register a single rule + // $rectorConfig->rule(\Ssch\TYPO3Rector\Rector\v9\v0\InjectAnnotationRector::class); + + /** + * Useful rule from RectorPHP itself to transform i.e. GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager') + * to GeneralUtility::makeInstance(\TYPO3\CMS\Core\Log\LogManager::class) calls. + * But be warned, sometimes it produces false positives (edge cases), so watch out + */ + // $rectorConfig->rule(\Rector\Php55\Rector\String_\StringClassNameToClassConstantRector::class); + + // Optional non-php file functionalities: + // @see https://github.com/sabbelasichon/typo3-rector/blob/main/docs/beyond_php_file_processors.md + + // Rewrite your extbase persistence class mapping from typoscript into php according to official docs. + // This processor will create a summarized file with all the typoscript rewrites combined into a single file. + /* $rectorConfig->ruleWithConfiguration(\Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v10\v0\ExtbasePersistenceTypoScriptRector::class, [ + \Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v10\v0\ExtbasePersistenceTypoScriptRector::FILENAME => __DIR__ . '/packages/acme_demo/Configuration/Extbase/Persistence/Classes.php', + ]); */ + // Add some general TYPO3 rules + $rectorConfig->rule(ConvertImplicitVariablesToExplicitGlobalsRector::class); + $rectorConfig->ruleWithConfiguration(ExtEmConfRector::class, [ + ExtEmConfRector::ADDITIONAL_VALUES_TO_BE_REMOVED => [] + ]); + + // Modernize your TypoScript include statements for files and move from to @import use the FileIncludeToImportStatementVisitor (introduced with TYPO3 9.0) + // $rectorConfig->rule(\Ssch\TYPO3Rector\FileProcessor\TypoScript\Rector\v9\v0\FileIncludeToImportStatementTypoScriptRector::class); +}; From b43af240f95a1b894ef363dc036c9cb1592d4867 Mon Sep 17 00:00:00 2001 From: Tim Weisenberger Date: Mon, 29 Jan 2024 10:51:31 +0100 Subject: [PATCH 2/2] feat: Add cdn base to css files --- Classes/EventListener/AddCdnToResource.php | 25 ++------------- .../AddFileCacheTagForTypolink.php | 6 ++-- Classes/Service/BaseUriService.php | 32 +++++++++++++++++++ Classes/Xclass/PageRenderer.php | 28 ++++++++++++++++ Configuration/Services.yaml | 4 +++ ext_localconf.php | 12 +++++++ 6 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 Classes/Service/BaseUriService.php create mode 100644 Classes/Xclass/PageRenderer.php create mode 100644 ext_localconf.php diff --git a/Classes/EventListener/AddCdnToResource.php b/Classes/EventListener/AddCdnToResource.php index 2ca86f9..e395de0 100644 --- a/Classes/EventListener/AddCdnToResource.php +++ b/Classes/EventListener/AddCdnToResource.php @@ -4,9 +4,7 @@ namespace Netlogix\Nxsimplecdn\EventListener; -use InvalidArgumentException; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Message\UriInterface; +use Netlogix\Nxsimplecdn\Service\BaseUriService; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Http\Uri; use TYPO3\CMS\Core\Resource\Driver\DriverInterface; @@ -16,7 +14,6 @@ use TYPO3\CMS\Core\Resource\ProcessedFile; use TYPO3\CMS\Core\Resource\ResourceInterface; use TYPO3\CMS\Core\Resource\ResourceStorageInterface; -use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Utility\GeneralUtility; class AddCdnToResource @@ -47,7 +44,7 @@ public function __invoke(GeneratePublicUrlForResourceEvent $event): void private function addCdnPrefixToUrl(ResourceInterface $resourceObject, DriverInterface $driver): string { $publicUrl = $driver->getPublicUrl($resourceObject->getIdentifier()); - $cdnBaseUrl = $this->getCdnBase(); + $cdnBaseUrl = GeneralUtility::makeInstance(BaseUriService::class)->getBaseUri(); if (!$resourceObject instanceof ProcessedFile) { $publicUrl = GeneralUtility::createVersionNumberedFilename($publicUrl); } @@ -55,22 +52,4 @@ private function addCdnPrefixToUrl(ResourceInterface $resourceObject, DriverInte return (string) (new Uri($publicUrl))->withScheme('https') ->withHost($cdnBaseUrl->getHost()); } - - private function getCdnBase(): UriInterface - { - $request = $this->getRequest(); - $site = $request->getAttribute('site'); - assert($site instanceof Site); - - try { - return new Uri($site->getAttribute('cdnBase')); - } catch (InvalidArgumentException) { - return $site->getBase(); - } - } - - private function getRequest(): ServerRequestInterface - { - return $GLOBALS['TYPO3_REQUEST']; - } } diff --git a/Classes/EventListener/AddFileCacheTagForTypolink.php b/Classes/EventListener/AddFileCacheTagForTypolink.php index 0332a98..a7e42c7 100644 --- a/Classes/EventListener/AddFileCacheTagForTypolink.php +++ b/Classes/EventListener/AddFileCacheTagForTypolink.php @@ -24,7 +24,9 @@ public function __invoke(AfterLinkIsGeneratedEvent $event): void $linkService = GeneralUtility::makeInstance(LinkService::class); $resolvedLink = $linkService->resolveByStringRepresentation( - $event->getContentObjectRenderer()->parameters['href'] + $event + ->getContentObjectRenderer() + ->parameters['href'] ); if (!array_key_exists('file', $resolvedLink)) { @@ -35,7 +37,7 @@ public function __invoke(AfterLinkIsGeneratedEvent $event): void $file = $resolvedLink['file']; $this->getTypoScriptFrontendController() - ->addCacheTags(['sys_file_' . (int)$file->getProperty('uid')]); + ->addCacheTags(['sys_file_' . (int) $file->getProperty('uid')]); } private function getTypoScriptFrontendController(): TypoScriptFrontendController diff --git a/Classes/Service/BaseUriService.php b/Classes/Service/BaseUriService.php new file mode 100644 index 0000000..02b9779 --- /dev/null +++ b/Classes/Service/BaseUriService.php @@ -0,0 +1,32 @@ +getRequest(); + $site = $request->getAttribute('site'); + assert($site instanceof Site); + + try { + return new Uri($site->getAttribute('cdnBase')); + } catch (InvalidArgumentException) { + return $site->getBase(); + } + } + + protected function getRequest(): ServerRequestInterface + { + return $GLOBALS['TYPO3_REQUEST']; + } +} diff --git a/Classes/Xclass/PageRenderer.php b/Classes/Xclass/PageRenderer.php new file mode 100644 index 0000000..715fb95 --- /dev/null +++ b/Classes/Xclass/PageRenderer.php @@ -0,0 +1,28 @@ +getApplicationType() === 'BE') { + return $file; + } + + $baseUri = GeneralUtility::makeInstance(BaseUriService::class) + ->getBaseUri(); + + return (string) (new Uri($file)) + ->withScheme('https') + ->withHost($baseUri->getHost()); + } +} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 679a40b..42d18b1 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -45,3 +45,7 @@ services: - name: event.listener identifier: 'nxsimplecdn/addFileCacheTagForTypolink' event: TYPO3\CMS\Frontend\Event\AfterLinkIsGeneratedEvent + + Netlogix\Nxsimplecdn\Xclass\PageRenderer: + arguments: + $assetsCache: '@cache.assets' diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..d7de219 --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,12 @@ +