From d01b837b834ed0f1026fb36f176d3b257c14ba63 Mon Sep 17 00:00:00 2001 From: Matthias Vogel Date: Tue, 17 Mar 2026 10:25:17 +0100 Subject: [PATCH 1/2] [TASK] upgrade to TYPO3v14 + drop 11 and 12 support --- .../BootCompletedEventListener.php | 4 +- .../ConsoleCommandEventListener.php | 14 +++- .../FileProcessingEventListener.php | 3 + Classes/EventListener/MailEventListener.php | 3 + .../AdminpanelSqlLoggingMiddleware.php | 44 ------------ Classes/Middleware/WrapMiddleware.php | 6 -- .../Middleware/XClassMiddlewareDispatcher.php | 6 -- Classes/ServiceProvider.php | 42 ++--------- Classes/SqlLogging/SqlLoggerCore11.php | 50 ------------- Configuration/Services.yaml | 72 ++++++++----------- composer.json | 6 +- ext_emconf.php | 9 ++- ext_localconf.php | 18 ++--- 13 files changed, 72 insertions(+), 205 deletions(-) delete mode 100644 Classes/Middleware/AdminpanelSqlLoggingMiddleware.php delete mode 100644 Classes/SqlLogging/SqlLoggerCore11.php diff --git a/Classes/EventListener/BootCompletedEventListener.php b/Classes/EventListener/BootCompletedEventListener.php index e3f7b3d..4c9e8b4 100644 --- a/Classes/EventListener/BootCompletedEventListener.php +++ b/Classes/EventListener/BootCompletedEventListener.php @@ -4,12 +4,13 @@ namespace Kanti\ServerTiming\EventListener; -use Kanti\ServerTiming\SqlLogging\SqlLoggerCore11; use Kanti\ServerTiming\Utility\TimingUtility; +use TYPO3\CMS\Core\Attribute\AsEventListener; use TYPO3\CMS\Core\Core\Event\BootCompletedEvent; final class BootCompletedEventListener { + #[AsEventListener('kanti/server-timing/boot-completed-event-listener')] public function __invoke(BootCompletedEvent $event): void { // we initialize TimingUtility here @@ -17,6 +18,5 @@ public function __invoke(BootCompletedEvent $event): void // at this point, the TimingUtility is found in the container, but at the shutdown state the TimingUtility is not found in the container. // so if we initialize it right here and save it inside a static variable, then everything works as expected. (not the sentry part :/ ) TimingUtility::getInstance(); - SqlLoggerCore11::registerSqlLogger(); } } diff --git a/Classes/EventListener/ConsoleCommandEventListener.php b/Classes/EventListener/ConsoleCommandEventListener.php index 51d3647..67bc939 100644 --- a/Classes/EventListener/ConsoleCommandEventListener.php +++ b/Classes/EventListener/ConsoleCommandEventListener.php @@ -6,21 +6,25 @@ use Exception; use Kanti\ServerTiming\Dto\ScriptResult; +use Kanti\ServerTiming\Dto\StopWatch; use Kanti\ServerTiming\Utility\TimingUtility; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Kanti\ServerTiming\Dto\StopWatch; +use Symfony\Component\Console\Output\OutputInterface; +use TYPO3\CMS\Core\Attribute\AsEventListener; final class ConsoleCommandEventListener { /** @var StopWatch[] */ private array $stopWatches = []; + #[AsEventListener('kanti/server-timing/console-command-event-listener')] public function start(ConsoleCommandEvent $event): void { $this->stopWatches[] = TimingUtility::stopWatch('console.command', (string)$event->getCommand()?->getName()); } + #[AsEventListener('kanti/server-timing/console-terminate-event-listener')] public function stop(ConsoleTerminateEvent $event): void { $stopWatch = array_pop($this->stopWatches); @@ -32,5 +36,13 @@ public function stop(ConsoleTerminateEvent $event): void if (!$this->stopWatches) { TimingUtility::getInstance()->shutdown(ScriptResult::fromCli($event->getExitCode())); } + $event->getOutput()->writeln( + sprintf( + "server_timing: Command \"%s\" took %.4fs", + $event->getCommand()->getName(), + $stopWatch->getDuration(), + ), + OutputInterface::VERBOSITY_VERBOSE, + ); } } diff --git a/Classes/EventListener/FileProcessingEventListener.php b/Classes/EventListener/FileProcessingEventListener.php index 7567b52..54020dc 100644 --- a/Classes/EventListener/FileProcessingEventListener.php +++ b/Classes/EventListener/FileProcessingEventListener.php @@ -6,6 +6,7 @@ use Kanti\ServerTiming\Dto\StopWatch; use Kanti\ServerTiming\Utility\TimingUtility; +use TYPO3\CMS\Core\Attribute\AsEventListener; use TYPO3\CMS\Core\Resource\Event\AfterFileProcessingEvent; use TYPO3\CMS\Core\Resource\Event\BeforeFileProcessingEvent; @@ -13,6 +14,7 @@ final class FileProcessingEventListener { public StopWatch|null $stopWatch = null; + #[AsEventListener('kanti/server-timing/file-processing')] public function before(BeforeFileProcessingEvent $event): void { if (!$event->getProcessedFile()->isProcessed()) { @@ -21,6 +23,7 @@ public function before(BeforeFileProcessingEvent $event): void } } + #[AsEventListener('kanti/server-timing/file-processing')] public function after(AfterFileProcessingEvent $event): void { $this->stopWatch?->stopIfNot(); diff --git a/Classes/EventListener/MailEventListener.php b/Classes/EventListener/MailEventListener.php index d162d51..bd52a44 100644 --- a/Classes/EventListener/MailEventListener.php +++ b/Classes/EventListener/MailEventListener.php @@ -7,6 +7,7 @@ use Kanti\ServerTiming\Dto\StopWatch; use Kanti\ServerTiming\Utility\TimingUtility; use Symfony\Component\Mime\Email; +use TYPO3\CMS\Core\Attribute\AsEventListener; use TYPO3\CMS\Core\Mail\Event\AfterMailerSentMessageEvent; use TYPO3\CMS\Core\Mail\Event\BeforeMailerSentMessageEvent; @@ -14,6 +15,7 @@ final class MailEventListener { public ?StopWatch $stopWatch = null; + #[AsEventListener('kanti/server-timing/mail-event-listener')] public function start(BeforeMailerSentMessageEvent $event): void { $info = ''; @@ -27,6 +29,7 @@ public function start(BeforeMailerSentMessageEvent $event): void $this->stopWatch = TimingUtility::stopWatch('mail', $info); } + #[AsEventListener('kanti/server-timing/mail-event-listener')] public function stop(AfterMailerSentMessageEvent $event): void { $this->stopWatch?->stopIfNot(); diff --git a/Classes/Middleware/AdminpanelSqlLoggingMiddleware.php b/Classes/Middleware/AdminpanelSqlLoggingMiddleware.php deleted file mode 100644 index ab9c4af..0000000 --- a/Classes/Middleware/AdminpanelSqlLoggingMiddleware.php +++ /dev/null @@ -1,44 +0,0 @@ -=12 is compatible - */ -final class AdminpanelSqlLoggingMiddleware implements MiddlewareInterface -{ - /** - * Enable SQL Logging as early as possible to catch all queries if the admin panel is active - */ - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - if (StateUtility::isActivatedForUser() && StateUtility::isOpen()) { - $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); - $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); - $connection->getConfiguration()->setSQLLogger( - new LoggerChain( - array_filter( - [ - GeneralUtility::makeInstance(DoctrineSqlLogger::class), - $connection->getConfiguration()->getSQLLogger(), - ] - ) - ) - ); - } - - return $handler->handle($request); - } -} diff --git a/Classes/Middleware/WrapMiddleware.php b/Classes/Middleware/WrapMiddleware.php index d4eb330..dd3b59b 100644 --- a/Classes/Middleware/WrapMiddleware.php +++ b/Classes/Middleware/WrapMiddleware.php @@ -35,15 +35,9 @@ public function handle(ServerRequestInterface $request): ResponseInterface self::$middlewareIn?->stopIfNot(); self::$middlewareIn = TimingUtility::stopWatch($this->isKernel ? 'requestHandler' : 'middleware.in', $this->info); - if ($this->isKernel) { - $request->getAttribute('middleware.in.total')?->stop(); - } $response = $this->requestHandler->handle($request); - if ($this->isKernel) { - TimingUtility::start('middleware.out.total'); - } // if it was the requestHandler: self::$middlewareIn?->stopIfNot(); diff --git a/Classes/Middleware/XClassMiddlewareDispatcher.php b/Classes/Middleware/XClassMiddlewareDispatcher.php index ee1701c..479c365 100644 --- a/Classes/Middleware/XClassMiddlewareDispatcher.php +++ b/Classes/Middleware/XClassMiddlewareDispatcher.php @@ -35,7 +35,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface $stop->startTime = $_SERVER["REQUEST_TIME_FLOAT"]; $stop->stop(); - $request = $request->withAttribute('middleware.in.total', TimingUtility::stopWatch('middleware.in.total')); if ($this->tip instanceof WrapMiddleware) { $this->tip->isFirst(); } @@ -46,11 +45,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface $response = $immediateResponseException->getResponse(); } - try { - TimingUtility::end('middleware.out.total'); - } catch (Exception) { - } - return TimingUtility::getInstance()->shutdown(ScriptResult::fromRequest($request, $response)) ?? $response; } diff --git a/Classes/ServiceProvider.php b/Classes/ServiceProvider.php index 9a8e3b2..fe870c2 100644 --- a/Classes/ServiceProvider.php +++ b/Classes/ServiceProvider.php @@ -9,14 +9,15 @@ use Psr\Container\ContainerInterface; use TYPO3\CMS\Backend\Http\Application as ApplicationBE; use TYPO3\CMS\Backend\Http\RequestHandler as RequestHandlerBe; -use TYPO3\CMS\Core\Configuration\ConfigurationManager; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Package\AbstractServiceProvider; -use TYPO3\CMS\Core\Routing\BackendEntryPointResolver; use TYPO3\CMS\Frontend\Http\Application as ApplicationFE; use TYPO3\CMS\Frontend\Http\RequestHandler as RequestHandlerFE; +/** + * @deprecated can be removed if TYPO3 14 is lowest supported version + */ final class ServiceProvider extends AbstractServiceProvider { protected static function getPackagePath(): string @@ -34,6 +35,9 @@ public static function getPackageName(): string */ public function getFactories(): array { + if ((new Typo3Version())->getMajorVersion() >= 14) { + return []; + } return [ ApplicationFE::class => self::getApplicationFE(...), ApplicationBE::class => self::getApplicationBE(...), @@ -47,25 +51,8 @@ public static function getApplicationFE(ContainerInterface $container): Applicat $container->get('frontend.middlewares'), $container, ); - if (version_compare((new Typo3Version())->getBranch(), '13.0', '>=')) { - return new ApplicationFE( - $requestHandler, - $container->get(Context::class), - ); - } - - if (version_compare((new Typo3Version())->getBranch(), '12.0', '>=') && class_exists(BackendEntryPointResolver::class)) { - return new ApplicationFE( - $requestHandler, - $container->get(ConfigurationManager::class), - $container->get(Context::class), - $container->get(BackendEntryPointResolver::class), - ); - } - return new ApplicationFE( $requestHandler, - $container->get(ConfigurationManager::class), $container->get(Context::class), ); } @@ -77,25 +64,8 @@ public static function getApplicationBE(ContainerInterface $container): Applicat $container->get('backend.middlewares'), $container, ); - if (version_compare((new Typo3Version())->getBranch(), '13.0', '>=')) { - return new ApplicationBE( - $requestHandler, - $container->get(Context::class), - ); - } - - if (version_compare((new Typo3Version())->getBranch(), '12.0', '>=') && class_exists(BackendEntryPointResolver::class)) { - return new ApplicationBE( - $requestHandler, - $container->get(ConfigurationManager::class), - $container->get(Context::class), - $container->get(BackendEntryPointResolver::class), - ); - } - return new ApplicationBE( $requestHandler, - $container->get(ConfigurationManager::class), $container->get(Context::class), ); } diff --git a/Classes/SqlLogging/SqlLoggerCore11.php b/Classes/SqlLogging/SqlLoggerCore11.php deleted file mode 100644 index b93b847..0000000 --- a/Classes/SqlLogging/SqlLoggerCore11.php +++ /dev/null @@ -1,50 +0,0 @@ -=12 is compatible - */ -final class SqlLoggerCore11 -{ - /** - * @deprecated can be removed if only TYPO3 >=12 is compatible - */ - public static function registerSqlLogger(): void - { - if (version_compare((new Typo3Version())->getBranch(), '12.3', '>=')) { - return; - } - - $doctrineSqlLogger = new DoctrineSqlLogger(); - - $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class); - $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME); - $connection->getConfiguration()->setSQLLogger( - new class ($doctrineSqlLogger) implements SQLLogger { - public function __construct(private readonly DoctrineSqlLogger $doctrineSqlLogger) - { - } - - public function startQuery($sql, ?array $params = null, ?array $types = null): void - { - $this->doctrineSqlLogger->startQuery($sql); - } - - public function stopQuery(): void - { - $this->doctrineSqlLogger->stopQuery(); - } - } - ); - } -} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index cdda25d..7014cba 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=../../../../vendor/symfony/dependency-injection/Loader/schema/services.schema.json services: _defaults: autowire: true @@ -17,48 +18,35 @@ services: Kanti\ServerTiming\Service\SentryServiceInterface: class: Kanti\ServerTiming\Service\SentryService - Kanti\ServerTiming\EventListener\ConsoleCommandEventListener: - tags: - - - name: event.listener - identifier: kanti/server-timing/console-command-event-listener - event: Symfony\Component\Console\Event\ConsoleCommandEvent - method: start - - - name: event.listener - identifier: kanti/server-timing/console-terminate-event-listener - event: Symfony\Component\Console\Event\ConsoleTerminateEvent - method: stop + TYPO3\CMS\Extbase\Mvc\Dispatcher: + class: Kanti\ServerTiming\Extbase\XClassExtbaseDispatcher - Kanti\ServerTiming\EventListener\MailEventListener: - tags: - - - name: event.listener - identifier: kanti/server-timing/mail-event-listener - event: TYPO3\CMS\Core\Mail\Event\BeforeMailerSentMessageEvent - method: start - - - name: event.listener - identifier: kanti/server-timing/mail-event-listener - event: TYPO3\CMS\Core\Mail\Event\AfterMailerSentMessageEvent - method: stop - Kanti\ServerTiming\EventListener\BootCompletedEventListener: - tags: - - - name: event.listener - identifier: kanti/server-timing/boot-completed-event-listener - event: TYPO3\CMS\Core\Core\Event\BootCompletedEvent + # this only works in >=v14 + TYPO3\CMS\Core\Http\Application: + arguments: + $requestHandler: '@xclass-core-middleware-dispatcher' + 'xclass-core-middleware-dispatcher': + class: Kanti\ServerTiming\Middleware\XClassMiddlewareDispatcher + arguments: + $kernel: '@TYPO3\CMS\Core\Http\RequestHandler' + $middlewares: '@core.middlewares' - Kanti\ServerTiming\EventListener\FileProcessingEventListener: - tags: - - - name: event.listener - identifier: kanti/server-timing/file-processing - event: TYPO3\CMS\Core\Resource\Event\BeforeFileProcessingEvent - method: before + # this only works in >=v14 + TYPO3\CMS\Backend\Http\Application: + arguments: + $requestHandler: '@xclass-backend-middleware-dispatcher' + 'xclass-backend-middleware-dispatcher': + class: Kanti\ServerTiming\Middleware\XClassMiddlewareDispatcher + arguments: + $kernel: '@TYPO3\CMS\Backend\Http\RequestHandler' + $middlewares: '@backend.middlewares' - - - name: event.listener - identifier: kanti/server-timing/file-processing - event: TYPO3\CMS\Core\Resource\Event\AfterFileProcessingEvent - method: after + # this only works in >=v14 + TYPO3\CMS\Frontend\Http\Application: + arguments: + $requestHandler: '@xclass-frontend-middleware-dispatcher' + 'xclass-frontend-middleware-dispatcher': + class: Kanti\ServerTiming\Middleware\XClassMiddlewareDispatcher + arguments: + $kernel: '@TYPO3\CMS\Frontend\Http\RequestHandler' + $middlewares: '@frontend.middlewares' diff --git a/composer.json b/composer.json index 242530d..f908a09 100644 --- a/composer.json +++ b/composer.json @@ -12,8 +12,8 @@ "require": { "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "composer-runtime-api": "^2.0.0", - "typo3/cms-core": "^11.0 || ^12.0 || ^13.0", - "typo3/cms-extbase": "^11.0 || ^12.0 || ^13.0" + "typo3/cms-core": "^13.0 || ^14.0", + "typo3/cms-extbase": "^13.0 || ^14.0" }, "require-dev": { "infection/infection": "^0.26.13 || ^0.27.11 || ^0.29.14", @@ -23,7 +23,7 @@ "saschaegerer/phpstan-typo3": "^1.10.1 || ^2.1.0", "sentry/sdk": "^3.5", "ssch/typo3-rector": "^2.6.4 || ^3.3.0", - "typo3/cms-adminpanel": "^11.0 || ^12.0 || ^13.0" + "typo3/cms-adminpanel": "^13.0 || ^14.0" }, "minimum-stability": "stable", "autoload": { diff --git a/ext_emconf.php b/ext_emconf.php index 99296c2..4db2006 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -3,6 +3,11 @@ use Composer\InstalledVersions; /** @var string $_EXTKEY */ +try { + $version = InstalledVersions::getPrettyVersion('kanti/server-timing'); +} catch (Exception $e) { + $version = '99.99.99'; // allow install in typo3-main +} $EM_CONF[$_EXTKEY] = [ 'title' => 'Kanti: server-timing', 'description' => 'Show timings of Database and HTTP Calls (send them to Sentry)', @@ -10,10 +15,10 @@ 'author' => 'Matthias Vogel', 'author_email' => 'git@kanti.de', 'state' => 'stable', - 'version' => InstalledVersions::getPrettyVersion('kanti/server-timing'), + 'version' => $version, 'constraints' => [ 'depends' => [ - 'typo3' => '11.0.0-13.4.99', + 'typo3' => '13.0.0-14.4.99', ], 'conflicts' => [], 'suggests' => [], diff --git a/ext_localconf.php b/ext_localconf.php index 2adf8ce..695b736 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,23 +1,15 @@ =12 -if (version_compare((new Typo3Version())->getBranch(), '12.3', '>=')) { - $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['driverMiddlewares']['server_timing_logging'] = LoggingMiddleware::class; -} else { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][SqlLogging::class] = [ - 'className' => AdminpanelSqlLoggingMiddleware::class, - ]; -} +$GLOBALS['TYPO3_CONF_VARS']['DB']['globalDriverMiddlewares']['global-driver-middleware-identifier'] = [ + 'target' => LoggingMiddleware::class, +]; $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][Dispatcher::class] = [ 'className' => XClassExtbaseDispatcher::class, From 8b9d491a0cc89c7dd8ab1a6c4c3a95d66898d7b3 Mon Sep 17 00:00:00 2001 From: Matthias Vogel Date: Tue, 28 Apr 2026 09:09:33 +0200 Subject: [PATCH 2/2] [TASK] fix pipeline --- .github/workflows/tasks.yml | 26 +- .../XClassContentDataProcessor.php | 48 +- .../XClassContentDataProcessorTrait.php | 48 ++ Classes/Dto/ScriptResult.php | 9 +- .../ConsoleCommandEventListener.php | 5 +- Classes/EventListener/MailEventListener.php | 3 +- Classes/Service/SentryService.php | 5 + Classes/Service/SentryServiceInterface.php | 2 + Classes/ServiceProvider.php | 1 + Classes/Utility/TimingUtility.php | 4 +- Tests/TimingUtilityTest.php | 3 +- composer.json | 7 +- ext_emconf.php | 3 +- ext_localconf.php | 2 + fractor.php | 21 + grumphp.yml | 4 + phpstan-baseline.neon | 530 +----------------- phpstan.neon | 2 +- rector.php | 5 +- 19 files changed, 128 insertions(+), 600 deletions(-) create mode 100644 Classes/DataProcessor/XClassContentDataProcessorTrait.php create mode 100644 fractor.php diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml index aaa9582..c0c656b 100644 --- a/.github/workflows/tasks.yml +++ b/.github/workflows/tasks.yml @@ -11,28 +11,16 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2', '8.3', '8.4' ] - typo3: [ '11', '12', '13' ] + php: [ '8.2', '8.3', '8.4' ] + typo3: [ '13', '14' ] sentry: [ false, true ] - exclude: - - php: '8.1' - typo3: '13' - sentry: true - - php: '8.1' - typo3: '13' - sentry: false steps: - name: Setup PHP with PECL extension uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} -# - uses: mirromutth/mysql-action@v1.1 -# with: -# mysql version: '5.7' -# mysql database: 'typo3_test' -# mysql root password: 'root' - - uses: actions/checkout@v4 - - uses: actions/cache@v4 + - uses: actions/checkout@v6 + - uses: actions/cache@v5 with: path: ~/.composer/cache/files key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }} @@ -46,7 +34,7 @@ jobs: - run: composer test - run: jq 'del(.logs.html)' infection.json > infection.json.new && mv infection.json.new infection.json - run: composer infection - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} file: Resources/Public/test-result/clover.xml @@ -64,7 +52,7 @@ jobs: TYPO3_API_PASSWORD: ${{ secrets.TYPO3_API_PASSWORD }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Get the version id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} @@ -72,7 +60,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' + php-version: '8.4' extensions: intl, mbstring, xml, soap, zip, curl - name: Install typo3/tailor diff --git a/Classes/DataProcessor/XClassContentDataProcessor.php b/Classes/DataProcessor/XClassContentDataProcessor.php index 652c9e4..a21af04 100644 --- a/Classes/DataProcessor/XClassContentDataProcessor.php +++ b/Classes/DataProcessor/XClassContentDataProcessor.php @@ -4,45 +4,19 @@ namespace Kanti\ServerTiming\DataProcessor; -use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Frontend\ContentObject\ContentDataProcessor; -use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; -final class XClassContentDataProcessor extends ContentDataProcessor -{ - /** - * @param array $configuration - * @param array $variables - * @return array - */ - public function process(ContentObjectRenderer $cObject, array $configuration, array $variables) - { - $processors = $configuration['dataProcessing.'] ?? []; - if (!$processors) { - return $variables; - } - - $processorKeys = ArrayUtility::filterAndSortByNumericKeys($processors); - $index = 1; - $newDataProcessing = []; - foreach ($processorKeys as $key) { - $processorClassOrAlias = $processors[$key]; - - $uniqId = uniqId(); - - $newDataProcessing[$index] = TrackingDataProcessor::class; - $newDataProcessing[$index . '.'] = ['key' => $key, 'processorOrAlias' => $processorClassOrAlias, 'type' => 'start', 'id' => $uniqId, 'for' => $cObject->getCurrentTable() . ':' . $cObject->data['uid']]; - $index++; - $newDataProcessing[$index] = $processorClassOrAlias; - $newDataProcessing[$index . '.'] = $processors[$key . '.'] ?? []; - $index++; - $newDataProcessing[$index] = TrackingDataProcessor::class; - $newDataProcessing[$index . '.'] = ['type' => 'stop', 'id' => $uniqId]; - $index++; - } +// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses - $configuration['dataProcessing.'] = $newDataProcessing; - - return parent::process($cObject, $configuration, $variables); +if ((new Typo3Version())->getMajorVersion() <= 13) { + final class XClassContentDataProcessor extends ContentDataProcessor + { + use XClassContentDataProcessorTrait; + } +} else { + final readonly class XClassContentDataProcessor extends ContentDataProcessor + { + use XClassContentDataProcessorTrait; } } diff --git a/Classes/DataProcessor/XClassContentDataProcessorTrait.php b/Classes/DataProcessor/XClassContentDataProcessorTrait.php new file mode 100644 index 0000000..59059f4 --- /dev/null +++ b/Classes/DataProcessor/XClassContentDataProcessorTrait.php @@ -0,0 +1,48 @@ + $configuration + * @param array $variables + * @return array + */ + public function process(ContentObjectRenderer $cObject, array $configuration, array $variables) + { + $processors = $configuration['dataProcessing.'] ?? []; + if (!$processors) { + return $variables; + } + + $processorKeys = ArrayUtility::filterAndSortByNumericKeys($processors); + $index = 1; + $newDataProcessing = []; + foreach ($processorKeys as $key) { + $processorClassOrAlias = $processors[$key]; + + $uniqId = uniqId(); + + $newDataProcessing[$index] = TrackingDataProcessor::class; + $newDataProcessing[$index . '.'] = ['key' => $key, 'processorOrAlias' => $processorClassOrAlias, 'type' => 'start', 'id' => $uniqId, 'for' => $cObject->getCurrentTable() . ':' . $cObject->data['uid']]; + $index++; + $newDataProcessing[$index] = $processorClassOrAlias; + $newDataProcessing[$index . '.'] = $processors[$key . '.'] ?? []; + $index++; + $newDataProcessing[$index] = TrackingDataProcessor::class; + $newDataProcessing[$index . '.'] = ['type' => 'stop', 'id' => $uniqId]; + $index++; + } + + $configuration['dataProcessing.'] = $newDataProcessing; + + return parent::process($cObject, $configuration, $variables); + } +} diff --git a/Classes/Dto/ScriptResult.php b/Classes/Dto/ScriptResult.php index 47474fe..38e3e88 100644 --- a/Classes/Dto/ScriptResult.php +++ b/Classes/Dto/ScriptResult.php @@ -9,10 +9,13 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Http\ServerRequestFactory; -final class ScriptResult +final readonly class ScriptResult { - private function __construct(public readonly ?ServerRequestInterface $request, public readonly ?ResponseInterface $response, public readonly ?int $cliExitCode) - { + private function __construct( + public ?ServerRequestInterface $request, + public ?ResponseInterface $response, + public ?int $cliExitCode, + ) { } public static function fromRequest(ServerRequestInterface $request, ?ResponseInterface $response = null): ScriptResult diff --git a/Classes/EventListener/ConsoleCommandEventListener.php b/Classes/EventListener/ConsoleCommandEventListener.php index 67bc939..1eb04b5 100644 --- a/Classes/EventListener/ConsoleCommandEventListener.php +++ b/Classes/EventListener/ConsoleCommandEventListener.php @@ -36,10 +36,11 @@ public function stop(ConsoleTerminateEvent $event): void if (!$this->stopWatches) { TimingUtility::getInstance()->shutdown(ScriptResult::fromCli($event->getExitCode())); } + $event->getOutput()->writeln( sprintf( - "server_timing: Command \"%s\" took %.4fs", - $event->getCommand()->getName(), + 'server_timing: Command "%s" took %.4fs', + (string)$event->getCommand()?->getName(), $stopWatch->getDuration(), ), OutputInterface::VERBOSITY_VERBOSE, diff --git a/Classes/EventListener/MailEventListener.php b/Classes/EventListener/MailEventListener.php index bd52a44..216e964 100644 --- a/Classes/EventListener/MailEventListener.php +++ b/Classes/EventListener/MailEventListener.php @@ -4,6 +4,7 @@ namespace Kanti\ServerTiming\EventListener; +use Symfony\Component\Mime\Address; use Kanti\ServerTiming\Dto\StopWatch; use Kanti\ServerTiming\Utility\TimingUtility; use Symfony\Component\Mime\Email; @@ -21,7 +22,7 @@ public function start(BeforeMailerSentMessageEvent $event): void $info = ''; $message = $event->getMessage(); if ($message instanceof Email) { - $emails = implode(', ', array_map(static fn($address): string => $address->getAddress(), $message->getTo())); + $emails = implode(', ', array_map(static fn(Address $address): string => $address->getAddress(), $message->getTo())); $info = $message->getSubject() . ' -> ' . $emails; } diff --git a/Classes/Service/SentryService.php b/Classes/Service/SentryService.php index 2c18fda..4a33278 100644 --- a/Classes/Service/SentryService.php +++ b/Classes/Service/SentryService.php @@ -4,6 +4,7 @@ namespace Kanti\ServerTiming\Service; +use Exception; use GuzzleHttp\Psr7\Uri; use Kanti\ServerTiming\Dto\ScriptResult; use Kanti\ServerTiming\Dto\StopWatch; @@ -81,6 +82,10 @@ public function sendSentryTrace(ScriptResult $result, array $stopWatches): ?Resp continue; } + if ($stack === []) { + throw new Exception('No parent span found for stopWatch ' . $stopWatch->key, 7800196395); + } + $parent = $stack[array_key_last($stack)]; if ($stopWatch->span) { $span = $stopWatch->span; diff --git a/Classes/Service/SentryServiceInterface.php b/Classes/Service/SentryServiceInterface.php index 8831445..093c807 100755 --- a/Classes/Service/SentryServiceInterface.php +++ b/Classes/Service/SentryServiceInterface.php @@ -1,5 +1,7 @@ getMajorVersion() >= 14) { return []; } + return [ ApplicationFE::class => self::getApplicationFE(...), ApplicationBE::class => self::getApplicationBE(...), diff --git a/Classes/Utility/TimingUtility.php b/Classes/Utility/TimingUtility.php index e00367a..a958309 100644 --- a/Classes/Utility/TimingUtility.php +++ b/Classes/Utility/TimingUtility.php @@ -43,7 +43,7 @@ public function __construct(private readonly RegisterShutdownFunctionInterface $ public static function getInstance(): TimingUtility { - return static::$instance ??= GeneralUtility::makeInstance(TimingUtility::class, new RegisterShutdownFunction(), new ConfigService()); + return self::$instance ??= GeneralUtility::makeInstance(TimingUtility::class, new RegisterShutdownFunction(), new ConfigService()); } /** @var StopWatch[] */ @@ -189,7 +189,7 @@ public function shutdown(ScriptResult $result): ?ResponseInterface private function humanReadableFileSize(int $size): string { $fileSizeNames = [" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB"]; - $i = floor(log($size, self::BYTE_MULTIPLICATOR)); + $i = (int)floor(log($size, self::BYTE_MULTIPLICATOR)); return $size ? round($size / (self::BYTE_MULTIPLICATOR ** $i), 2) . $fileSizeNames[$i] : '0 Bytes'; } diff --git a/Tests/TimingUtilityTest.php b/Tests/TimingUtilityTest.php index 04f5176..ebd7b7e 100644 --- a/Tests/TimingUtilityTest.php +++ b/Tests/TimingUtilityTest.php @@ -315,7 +315,7 @@ public function addSentryTraceHeaders(RequestInterface $request, StopWatch $stop /** * @param list $stopWatches */ - public function sendSentryTrace(ScriptResult $result, array $stopWatches): ?ResponseInterface + public function sendSentryTrace(ScriptResult $result, array $stopWatches): ResponseInterface { $sortedWatches = $stopWatches; usort($sortedWatches, static fn($a, $b): int => $b->stopTime <=> $a->stopTime); @@ -443,7 +443,6 @@ public function chunkStringArray(array $timings, int $maxLength, array $expected { $reflection = new ReflectionClass(TimingUtility::class); $reflectionMethod = $reflection->getMethod('chunkStringArray'); - $reflectionMethod->setAccessible(true); $result = $reflectionMethod->invoke($this->getTestInstance(), $timings, $maxLength); self::assertSame($expected, $result); diff --git a/composer.json b/composer.json index f908a09..06ac972 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", "composer-runtime-api": "^2.0.0", "typo3/cms-core": "^13.0 || ^14.0", "typo3/cms-extbase": "^13.0 || ^14.0" @@ -19,8 +19,8 @@ "infection/infection": "^0.26.13 || ^0.27.11 || ^0.29.14", "phpstan/extension-installer": "^1.1", "phpunit/phpunit": "^10 || ^11", - "pluswerk/grumphp-config": "^7 || ^10", - "saschaegerer/phpstan-typo3": "^1.10.1 || ^2.1.0", + "pluswerk/grumphp-config": "^7 || ^10 || ^11", + "saschaegerer/phpstan-typo3": "^2.1.0 || ^3.0.1", "sentry/sdk": "^3.5", "ssch/typo3-rector": "^2.6.4 || ^3.3.0", "typo3/cms-adminpanel": "^13.0 || ^14.0" @@ -38,6 +38,7 @@ }, "config": { "allow-plugins": { + "a9f/fractor-extension-installer": true, "ergebnis/composer-normalize": true, "infection/extension-installer": true, "php-http/discovery": false, diff --git a/ext_emconf.php b/ext_emconf.php index 4db2006..1c67134 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -5,9 +5,10 @@ /** @var string $_EXTKEY */ try { $version = InstalledVersions::getPrettyVersion('kanti/server-timing'); -} catch (Exception $e) { +} catch (Exception) { $version = '99.99.99'; // allow install in typo3-main } + $EM_CONF[$_EXTKEY] = [ 'title' => 'Kanti: server-timing', 'description' => 'Show timings of Database and HTTP Calls (send them to Sentry)', diff --git a/ext_localconf.php b/ext_localconf.php index 695b736..6b9e8bd 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,5 +1,7 @@ withPaths(array_filter(explode("\n", (string)shell_exec("git ls-files | xargs ls -d 2>/dev/null")))) + ->withSets([ + ...FractorSettings::sets(true), + ]) + ->withRules([ + ...FractorSettings::rules(), + ]) + ->withOptions([ + ...FractorSettings::options(), + ]) + ->withSkip([ + __DIR__ . '/phpunit.xml', + ]); diff --git a/grumphp.yml b/grumphp.yml index 9ad8ce8..4755ef3 100644 --- a/grumphp.yml +++ b/grumphp.yml @@ -14,3 +14,7 @@ parameters: convention.rector_enabled: true convention.rector_config: rector.php convention.rector_clear-cache: false + convention.fractor_ignore_pattern: { } + convention.fractor_enable: true + convention.fractor_config: fractor.php + convention.fractor_clear-cache: false diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index bd8c450..2187918 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,474 +1,10 @@ parameters: ignoreErrors: - - message: "#^Parameter \\#1 \\$loggers of class Doctrine\\\\DBAL\\\\Logging\\\\LoggerChain constructor expects iterable\\, array\\ given\\.$#" + message: '#^Trait Kanti\\ServerTiming\\DataProcessor\\XClassContentDataProcessorTrait is used zero times and is not analysed\.$#' + identifier: trait.unused count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: "#^Using nullsafe method call on non\\-nullable type Kanti\\\\ServerTiming\\\\Dto\\\\StopWatch\\. Use \\-\\> instead\\.$#" - count: 1 - path: Classes/Middleware/WrapMiddleware.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 2 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 3 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 2 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 3 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$configurationManager of class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager, TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context given\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$configurationManager of class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager, TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context given\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#1 \\$loggers of class Doctrine\\\\DBAL\\\\Logging\\\\LoggerChain constructor expects iterable\\, array\\ given\\.$#" - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: "#^Call to method getMessage\\(\\) on an unknown class TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\BeforeMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Parameter \\$event of method Kanti\\\\ServerTiming\\\\EventListener\\\\MailEventListener\\:\\:start\\(\\) has invalid type TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\BeforeMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Parameter \\$event of method Kanti\\\\ServerTiming\\\\EventListener\\\\MailEventListener\\:\\:stop\\(\\) has invalid type TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\AfterMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Using nullsafe method call on non\\-nullable type Kanti\\\\ServerTiming\\\\Dto\\\\StopWatch\\. Use \\-\\> instead\\.$#" - count: 1 - path: Classes/Middleware/WrapMiddleware.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 4 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 4 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 3 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 3 parameters, 4 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Property Kanti\\\\ServerTiming\\\\Dto\\\\StopWatch\\:\\:\\$span has unknown class Sentry\\\\Tracing\\\\Span as its type\\.$#" - count: 1 - path: Classes/Dto/StopWatch.php - - - - message: "#^Call to method finish\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method finish\\(\\) on an unknown class Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method getOptions\\(\\) on an unknown class Sentry\\\\ClientInterface\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setData\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setDescription\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setName\\(\\) on an unknown class Sentry\\\\Tracing\\\\TransactionContext\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setOp\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setOp\\(\\) on an unknown class Sentry\\\\Tracing\\\\TransactionContext\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setParentSpanId\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setStartTimestamp\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setStartTimestamp\\(\\) on an unknown class Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method setStatus\\(\\) on an unknown class Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 2 - path: Classes/Service/SentryService.php - - - - message: "#^Call to method startChild\\(\\) on an unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to static method createFromHttpStatusCode\\(\\) on an unknown class Sentry\\\\Tracing\\\\SpanStatus\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to static method getCurrentHub\\(\\) on an unknown class Sentry\\\\SentrySdk\\.$#" - count: 3 - path: Classes/Service/SentryService.php - - - - message: "#^Call to static method ok\\(\\) on an unknown class Sentry\\\\Tracing\\\\SpanStatus\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to static method unknownError\\(\\) on an unknown class Sentry\\\\Tracing\\\\SpanStatus\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Class Sentry\\\\Tracing\\\\Span not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Function Sentry\\\\continueTrace not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Function Sentry\\\\getBaggage not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Function Sentry\\\\getTraceparent not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Instantiated class Sentry\\\\Tracing\\\\SpanContext not found\\.$#" - count: 2 - path: Classes/Service/SentryService.php - - - - message: "#^Instantiated class Sentry\\\\Tracing\\\\TransactionContext not found\\.$#" - count: 2 - path: Classes/Service/SentryService.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:addResultToTransaction\\(\\) has invalid return type Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:createTransactionContextFromCli\\(\\) has invalid return type Sentry\\\\Tracing\\\\TransactionContext\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:createTransactionContextFromRequest\\(\\) has invalid return type Sentry\\\\Tracing\\\\TransactionContext\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:getSentryClient\\(\\) has invalid return type Sentry\\\\ClientInterface\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:startTransaction\\(\\) has invalid return type Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^PHPDoc tag @var for variable \\$stack contains unknown class Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Parameter \\$span of method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:updateSpan\\(\\) has invalid type Sentry\\\\Tracing\\\\Span\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Parameter \\$transaction of method Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:addResultToTransaction\\(\\) has invalid type Sentry\\\\Tracing\\\\Transaction\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Property Kanti\\\\ServerTiming\\\\Service\\\\SentryService\\:\\:\\$transaction has unknown class Sentry\\\\Tracing\\\\Transaction as its type\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Used function Sentry\\\\continueTrace not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Used function Sentry\\\\getBaggage not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Used function Sentry\\\\getTraceparent not found\\.$#" - count: 1 - path: Classes/Service/SentryService.php - - - - message: "#^Call to an undefined method Doctrine\\\\DBAL\\\\Configuration\\:\\:getSQLLogger\\(\\)\\.$#" - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: "#^Call to an undefined method Doctrine\\\\DBAL\\\\Configuration\\:\\:setSQLLogger\\(\\)\\.$#" - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: "#^Instantiated class Doctrine\\\\DBAL\\\\Logging\\\\LoggerChain not found\\.$#" - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: "#^Using nullsafe method call on non\\-nullable type Kanti\\\\ServerTiming\\\\Dto\\\\StopWatch\\. Use \\-\\> instead\\.$#" - count: 1 - path: Classes/Middleware/WrapMiddleware.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 3 parameters, 2 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 4 parameters, 2 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 3 parameters, 2 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 4 parameters, 2 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$context of class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context, TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager given\\.$#" - count: 2 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$context of class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context, TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager given\\.$#" - count: 2 - path: Classes/ServiceProvider.php - - - - message: "#^Method Doctrine\\\\DBAL\\\\Driver\\\\Middleware\\\\AbstractStatementMiddleware\\:\\:execute\\(\\) invoked with 1 parameter, 0 required\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\:\\:execute\\(\\) has parameter \\$params with no type specified\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php - - - - message: "#^Call to an undefined method Doctrine\\\\DBAL\\\\Configuration\\:\\:setSQLLogger\\(\\)\\.$#" - count: 1 - path: Classes/SqlLogging/SqlLoggerCore11.php - - - - message: "#^Method class@anonymous/Classes/SqlLogging/SqlLoggerCore11\\.php\\:33\\:\\:startQuery\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#" - count: 1 - path: Classes/SqlLogging/SqlLoggerCore11.php - - - - message: "#^Method class@anonymous/Classes/SqlLogging/SqlLoggerCore11\\.php\\:33\\:\\:startQuery\\(\\) has parameter \\$sql with no type specified\\.$#" - count: 1 - path: Classes/SqlLogging/SqlLoggerCore11.php - - - - message: "#^Method class@anonymous/Classes/SqlLogging/SqlLoggerCore11\\.php\\:33\\:\\:startQuery\\(\\) has parameter \\$types with no value type specified in iterable type array\\.$#" - count: 1 - path: Classes/SqlLogging/SqlLoggerCore11.php - - - - message: "#^Call to method getMessage\\(\\) on an unknown class TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\BeforeMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Parameter \\$event of method Kanti\\\\ServerTiming\\\\EventListener\\\\MailEventListener\\:\\:start\\(\\) has invalid type TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\BeforeMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Parameter \\$event of method Kanti\\\\ServerTiming\\\\EventListener\\\\MailEventListener\\:\\:stop\\(\\) has invalid type TYPO3\\\\CMS\\\\Core\\\\Mail\\\\Event\\\\AfterMailerSentMessageEvent\\.$#" - count: 1 - path: Classes/EventListener/MailEventListener.php - - - - message: "#^Using nullsafe method call on non\\-nullable type Kanti\\\\ServerTiming\\\\Dto\\\\StopWatch\\. Use \\-\\> instead\\.$#" - count: 1 - path: Classes/Middleware/WrapMiddleware.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 2 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor invoked with 4 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 2 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor invoked with 4 parameters, 3 required\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$configurationManager of class TYPO3\\\\CMS\\\\Backend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager, TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context given\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Parameter \\#2 \\$configurationManager of class TYPO3\\\\CMS\\\\Frontend\\\\Http\\\\Application constructor expects TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\ConfigurationManager, TYPO3\\\\CMS\\\\Core\\\\Context\\\\Context given\\.$#" - count: 1 - path: Classes/ServiceProvider.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:__construct\\(\\) calls parent\\:\\:__construct\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:exec\\(\\) calls parent\\:\\:exec\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:prepare\\(\\) calls parent\\:\\:prepare\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:query\\(\\) calls parent\\:\\:query\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:prepare\\(\\) return type has no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\:\\:prepare\\(\\) should return Doctrine\\\\DBAL\\\\Driver\\\\Statement but returns Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingConnection.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver\\:\\:__construct\\(\\) calls parent\\:\\:__construct\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingDriver.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver\\:\\:connect\\(\\) calls parent\\:\\:connect\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingDriver.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver\\:\\:connect\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingDriver.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver\\:\\:connect\\(\\) should return Doctrine\\\\DBAL\\\\Driver\\\\Connection but returns Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingConnection\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingDriver.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingMiddleware\\:\\:wrap\\(\\) should return Doctrine\\\\DBAL\\\\Driver but returns Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingDriver\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingMiddleware.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\:\\:__construct\\(\\) calls parent\\:\\:__construct\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php - - - - message: "#^Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\:\\:execute\\(\\) calls parent\\:\\:execute\\(\\) but Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement does not extend any class\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\:\\:__construct\\(\\) has parameter \\$statement with no value type specified in iterable type Doctrine\\\\DBAL\\\\Driver\\\\Statement\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php - - - - message: "#^Method Kanti\\\\ServerTiming\\\\SqlLogging\\\\LoggingStatement\\:\\:execute\\(\\) has parameter \\$params with no type specified\\.$#" - count: 1 - path: Classes/SqlLogging/LoggingStatement.php + path: Classes/DataProcessor/XClassContentDataProcessorTrait.php - message: '#^Property Kanti\\ServerTiming\\Dto\\StopWatch\:\:\$span has unknown class Sentry\\Tracing\\Span as its type\.$#' @@ -476,24 +12,6 @@ parameters: count: 1 path: Classes/Dto/StopWatch.php - - - message: '#^Call to an undefined method Doctrine\\DBAL\\Configuration\:\:getSQLLogger\(\)\.$#' - identifier: method.notFound - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: '#^Call to an undefined method Doctrine\\DBAL\\Configuration\:\:setSQLLogger\(\)\.$#' - identifier: method.notFound - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - - - message: '#^Instantiated class Doctrine\\DBAL\\Logging\\LoggerChain not found\.$#' - identifier: class.notFound - count: 1 - path: Classes/Middleware/AdminpanelSqlLoggingMiddleware.php - - message: '#^Using nullsafe method call on non\-nullable type Kanti\\ServerTiming\\Dto\\StopWatch\. Use \-\> instead\.$#' identifier: nullsafe.neverNull @@ -716,42 +234,6 @@ parameters: count: 1 path: Classes/Service/SentryService.php - - - message: '#^Class TYPO3\\CMS\\Backend\\Http\\Application constructor invoked with 3 parameters, 2 required\.$#' - identifier: arguments.count - count: 1 - path: Classes/ServiceProvider.php - - - - message: '#^Class TYPO3\\CMS\\Backend\\Http\\Application constructor invoked with 4 parameters, 2 required\.$#' - identifier: arguments.count - count: 1 - path: Classes/ServiceProvider.php - - - - message: '#^Class TYPO3\\CMS\\Frontend\\Http\\Application constructor invoked with 3 parameters, 2 required\.$#' - identifier: arguments.count - count: 1 - path: Classes/ServiceProvider.php - - - - message: '#^Class TYPO3\\CMS\\Frontend\\Http\\Application constructor invoked with 4 parameters, 2 required\.$#' - identifier: arguments.count - count: 1 - path: Classes/ServiceProvider.php - - - - message: '#^Parameter \#2 \$context of class TYPO3\\CMS\\Backend\\Http\\Application constructor expects TYPO3\\CMS\\Core\\Context\\Context, TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager given\.$#' - identifier: argument.type - count: 2 - path: Classes/ServiceProvider.php - - - - message: '#^Parameter \#2 \$context of class TYPO3\\CMS\\Frontend\\Http\\Application constructor expects TYPO3\\CMS\\Core\\Context\\Context, TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager given\.$#' - identifier: argument.type - count: 2 - path: Classes/ServiceProvider.php - - message: '#^Method Doctrine\\DBAL\\Driver\\Middleware\\AbstractStatementMiddleware\:\:execute\(\) invoked with 1 parameter, 0 required\.$#' identifier: arguments.count @@ -788,12 +270,6 @@ parameters: count: 1 path: Tests/TimingUtilityTest.php - - - message: '#^Method Kanti\\ServerTiming\\Service\\SentryServiceInterface@anonymous/Tests/TimingUtilityTest\.php\:[0-9]+\:\:sendSentryTrace\(\) never returns null so it can be removed from the return type\.$#' - identifier: return.unusedType - count: 1 - path: Tests/TimingUtilityTest.php - - message: '#^Parameter \#1 \$expected of static method PHPUnit\\Framework\\Assert\:\:assertSame\(\) contains unresolvable type\.$#' identifier: argument.unresolvableType diff --git a/phpstan.neon b/phpstan.neon index bdc951d..f67d1f2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,4 +9,4 @@ parameters: requestGetAttributeMapping: middleware.in.total: Kanti\ServerTiming\Dto\StopWatch|null excludePaths: - - Classes/SqlLogging/SqlLoggerCore11.php + - Classes/DataProcessor/XClassContentDataProcessor.php diff --git a/rector.php b/rector.php index bbfff81..2e25403 100644 --- a/rector.php +++ b/rector.php @@ -9,6 +9,7 @@ use Rector\DeadCode\Rector\Cast\RecastingRemovalRector; use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPublicMethodParameterRector; use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByMethodCallTypeRector; +use Ssch\TYPO3Rector\CodeQuality\General\GeneralUtilityMakeInstanceToConstructorPropertyRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->parallel(); @@ -46,8 +47,8 @@ RecastingRemovalRector::class => [ __DIR__ . '/Classes/SqlLogging/LoggingConnection.php', ], - ParamTypeByMethodCallTypeRector::class => [ - __DIR__ . '/Classes/SqlLogging/SqlLoggerCore11.php', + GeneralUtilityMakeInstanceToConstructorPropertyRector::class => [ + __DIR__ . '/Classes/Utility/TimingUtility.php', ], //__DIR__ . '/src/Example', //__DIR__ . '/src/Example.php',