Completed
Branch master (d17104)
by Christian
21:20
created

QueryInformation::getContent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace TYPO3\CMS\Adminpanel\Modules\Debug;
5
6
/*
7
 * This file is part of the TYPO3 CMS project.
8
 *
9
 * It is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License, either version 2
11
 * of the License, or any later version.
12
 *
13
 * For the full copyright and license information, please read the
14
 * LICENSE.txt file that was distributed with this source code.
15
 *
16
 * The TYPO3 project - inspiring people to share!
17
 */
18
19
use Psr\Http\Message\ServerRequestInterface;
20
use TYPO3\CMS\Adminpanel\Log\DoctrineSqlLogger;
21
use TYPO3\CMS\Adminpanel\ModuleApi\AbstractSubModule;
22
use TYPO3\CMS\Adminpanel\ModuleApi\ContentProviderInterface;
23
use TYPO3\CMS\Adminpanel\ModuleApi\DataProviderInterface;
24
use TYPO3\CMS\Adminpanel\ModuleApi\ModuleData;
25
use TYPO3\CMS\Core\Database\ConnectionPool;
26
use TYPO3\CMS\Core\Utility\GeneralUtility;
27
use TYPO3\CMS\Fluid\View\StandaloneView;
28
29
/**
30
 * Admin Panel Query Information module for showing SQL Queries
31
 *
32
 * @internal
33
 */
34
class QueryInformation extends AbstractSubModule implements DataProviderInterface, ContentProviderInterface
35
{
36
    /**
37
     * Identifier for this Sub-module,
38
     * for example "preview" or "cache"
39
     *
40
     * @return string
41
     */
42
    public function getIdentifier(): string
43
    {
44
        return 'debug_queryinformation';
45
    }
46
47
    /**
48
     * Sub-Module label
49
     *
50
     * @return string
51
     */
52
    public function getLabel(): string
53
    {
54
        return $this->getLanguageService()->sL(
55
            'LLL:EXT:adminpanel/Resources/Private/Language/locallang_debug.xlf:submodule.queryInformation.label'
56
        );
57
    }
58
59
    /**
60
     * @param ServerRequestInterface $request
61
     * @return \TYPO3\CMS\Adminpanel\ModuleApi\ModuleData
62
     * @throws \Doctrine\DBAL\DBALException
63
     */
64
    public function getDataToStore(ServerRequestInterface $request): ModuleData
65
    {
66
        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
67
        $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
68
        $logger = $connection->getConfiguration()->getSQLLogger();
69
        $data = [];
70
        if ($logger instanceof DoctrineSqlLogger) {
71
            $queries = $logger->getQueries();
72
            $data['queries'] = $this->groupQueries($queries) ?? [];
73
            $data['totalTime'] = array_sum(array_column($queries, 'executionMS')) * 1000;
74
        }
75
        return new ModuleData($data);
76
    }
77
78
    /**
79
     * @param \TYPO3\CMS\Adminpanel\ModuleApi\ModuleData $data
80
     * @return string Returns content of admin panel
81
     */
82
    public function getContent(ModuleData $data): string
83
    {
84
        $view = new StandaloneView();
85
        $view->setTemplatePathAndFilename(
86
            'typo3/sysext/adminpanel/Resources/Private/Templates/Modules/Debug/QueryInformation.html'
87
        );
88
        $this->getLanguageService()->includeLLFile('EXT:adminpanel/Resources/Private/Language/locallang_debug.xlf');
89
        $view->assignMultiple($data->getArrayCopy());
90
        return $view->render();
91
    }
92
93
    /**
94
     * @param array $queries
95
     * @return array
96
     */
97
    protected function groupQueries(array $queries): array
98
    {
99
        $groupedQueries = [];
100
        foreach ($queries as $query) {
101
            $identifier = sha1($query['sql']) . sha1(implode(',', $query['backtrace']));
102
            if (is_array($query['params'])) {
103
                foreach ($query['params'] as $k => $param) {
104
                    if (is_array($param)) {
105
                        $query['params'][$k] = implode(',', $param);
106
                    }
107
                }
108
            }
109
            if (isset($groupedQueries[$identifier])) {
110
                $groupedQueries[$identifier]['count']++;
111
                $groupedQueries[$identifier]['time'] += ($query['executionMS'] * 1000);
112
                $groupedQueries[$identifier]['queries'][] = $query;
113
            } else {
114
                $groupedQueries[$identifier] = [
115
                    'sql' => $query['sql'],
116
                    'time' => $query['executionMS'] * 1000,
117
                    'count' => 1,
118
                    'queries' => [
119
                        $query,
120
                    ],
121
                ];
122
            }
123
        }
124
        uasort(
125
            $groupedQueries,
126
            function ($a, $b) {
127
                return $b['time'] <=> $a['time'];
128
            }
129
        );
130
        return $groupedQueries;
131
    }
132
}
133