From 20b2c0f55ad61c9d71d5a19dc21742680ba3d7cc Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Thu, 19 Mar 2026 15:17:17 +0100 Subject: [PATCH 1/2] Add non regression test --- .../nsrt/shopware-connection-profiler.php | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php diff --git a/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php b/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php new file mode 100644 index 0000000000..ad20175db9 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php @@ -0,0 +1,89 @@ +'|'::', args?: list, object?: object}> + * @phpstan-type QueryInfo array{ + * sql: string, + * executionMS: float, + * types: array, + * params: array, + * backtrace?: Backtrace + * } + * @phpstan-type SanitizedQueryInfo array{sql: string, executionMS: float, types: array<(int | string), ParameterType|int>, params: Data, runnable: bool, explainable: bool, backtrace?: Backtrace} + * @phpstan-type SanitizedQueryInfoGroup array{sql: string, executionMS: float, types: array<(int | string), ParameterType|int>, params: Data, runnable: bool, explainable: bool, backtrace?: Backtrace, count: int, index: int, executionPercent?: float} + */ +abstract class ConnectionProfiler +{ + /** + * @var ?array> + */ + public ?array $groupedQueries = null; + + /** + * @return array> + */ + abstract public function getQueries(): array; + + /** + * @return array> + */ + public function getGroupedQueries(): array + { + if ($this->groupedQueries !== null) { + return $this->groupedQueries; + } + + $this->groupedQueries = []; + $totalExecutionMS = 0; + foreach ($this->getQueries() as $connection => $queries) { + $connectionGroupedQueries = []; + foreach ($queries as $i => $query) { + $key = $query['sql']; + if (!isset($connectionGroupedQueries[$key])) { + $connectionGroupedQueries[$key] = $query; + $connectionGroupedQueries[$key]['executionMS'] = 0; + $connectionGroupedQueries[$key]['count'] = 0; + $connectionGroupedQueries[$key]['index'] = $i; // "Explain query" relies on query index in 'queries'. + } + + assertType("array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: 0, index: int}|array{sql: string, executionMS: float, types: array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); + $connectionGroupedQueries[$key]['executionMS'] += $query['executionMS']; + assertType("non-empty-array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<0, max>, index: int}>", $connectionGroupedQueries); + ++$connectionGroupedQueries[$key]['count']; + $totalExecutionMS += $query['executionMS']; + } + + assertType("array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); + usort($connectionGroupedQueries, static fn (array $a, array $b): int => $b['executionMS'] <=> $a['executionMS']); + $this->groupedQueries[$connection] = $connectionGroupedQueries; + } + + foreach ($this->groupedQueries as &$queries) { + foreach ($queries as &$query) { + $query['executionPercent'] = $this->executionTimePercentage($query['executionMS'], $totalExecutionMS); + } + unset($query); + } + unset($queries); + + assertType("list, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); + + return $this->groupedQueries; + } + + private function executionTimePercentage(float $executionTimeMS, float $totalExecutionTimeMS): float + { + if (!$totalExecutionTimeMS) { + return 0; + } + + return $executionTimeMS / $totalExecutionTimeMS * 100; + } +} From 819e3d3f800ae97b74f07a9e36f85d411a60b66f Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Thu, 19 Mar 2026 16:05:29 +0100 Subject: [PATCH 2/2] Smaller test --- .../nsrt/shopware-connection-profiler.php | 58 ++----------------- 1 file changed, 6 insertions(+), 52 deletions(-) diff --git a/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php b/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php index ad20175db9..ced23ea733 100644 --- a/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php +++ b/tests/PHPStan/Analyser/nsrt/shopware-connection-profiler.php @@ -4,45 +4,21 @@ use function PHPStan\Testing\assertType; -class Data {} class ParameterType {} /** - * @phpstan-type Backtrace list'|'::', args?: list, object?: object}> - * @phpstan-type QueryInfo array{ - * sql: string, - * executionMS: float, - * types: array, - * params: array, - * backtrace?: Backtrace - * } - * @phpstan-type SanitizedQueryInfo array{sql: string, executionMS: float, types: array<(int | string), ParameterType|int>, params: Data, runnable: bool, explainable: bool, backtrace?: Backtrace} - * @phpstan-type SanitizedQueryInfoGroup array{sql: string, executionMS: float, types: array<(int | string), ParameterType|int>, params: Data, runnable: bool, explainable: bool, backtrace?: Backtrace, count: int, index: int, executionPercent?: float} + * @phpstan-type SanitizedQueryInfo array{sql: string, executionMS: float, types: array<(int | string), ParameterType|int>} */ abstract class ConnectionProfiler { - /** - * @var ?array> - */ - public ?array $groupedQueries = null; - /** * @return array> */ abstract public function getQueries(): array; - /** - * @return array> - */ - public function getGroupedQueries(): array + public function getGroupedQueries(): void { - if ($this->groupedQueries !== null) { - return $this->groupedQueries; - } - - $this->groupedQueries = []; - $totalExecutionMS = 0; - foreach ($this->getQueries() as $connection => $queries) { + foreach ($this->getQueries() as $queries) { $connectionGroupedQueries = []; foreach ($queries as $i => $query) { $key = $query['sql']; @@ -53,37 +29,15 @@ public function getGroupedQueries(): array $connectionGroupedQueries[$key]['index'] = $i; // "Explain query" relies on query index in 'queries'. } - assertType("array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: 0, index: int}|array{sql: string, executionMS: float, types: array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); + assertType("array, count: 0, index: int}|array{sql: string, executionMS: float, types: array, count: int<1, max>, index: int}>", $connectionGroupedQueries); $connectionGroupedQueries[$key]['executionMS'] += $query['executionMS']; - assertType("non-empty-array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<0, max>, index: int}>", $connectionGroupedQueries); + assertType("non-empty-array, count: int<0, max>, index: int}>", $connectionGroupedQueries); ++$connectionGroupedQueries[$key]['count']; - $totalExecutionMS += $query['executionMS']; } - assertType("array, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); + assertType("array, count: int<1, max>, index: int}>", $connectionGroupedQueries); usort($connectionGroupedQueries, static fn (array $a, array $b): int => $b['executionMS'] <=> $a['executionMS']); - $this->groupedQueries[$connection] = $connectionGroupedQueries; - } - - foreach ($this->groupedQueries as &$queries) { - foreach ($queries as &$query) { - $query['executionPercent'] = $this->executionTimePercentage($query['executionMS'], $totalExecutionMS); - } - unset($query); } - unset($queries); - - assertType("list, params: Shopware\Core\Profiling\Doctrine\Data, runnable: bool, explainable: bool, backtrace?: list'|'::', args?: list, object?: object}>, count: int<1, max>, index: int}>", $connectionGroupedQueries); - - return $this->groupedQueries; } - private function executionTimePercentage(float $executionTimeMS, float $totalExecutionTimeMS): float - { - if (!$totalExecutionTimeMS) { - return 0; - } - - return $executionTimeMS / $totalExecutionTimeMS * 100; - } }