‪TYPO3CMS  10.4
OptimizeDatabaseTableAdditionalFieldProvider.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
26 
32 {
36  protected ‪$languageFile = 'LLL:EXT:scheduler/Resources/Private/Language/locallang.xlf';
37 
46  public function ‪getAdditionalFields(array &$taskInfo, $task, ‪SchedulerModuleController $schedulerModule)
47  {
48  $currentSchedulerModuleAction = $schedulerModule->‪getCurrentAction();
49 
50  // Initialize selected fields
51  if (empty($taskInfo['scheduler_optimizeDatabaseTables_selectedTables'])) {
52  $taskInfo['scheduler_optimizeDatabaseTables_selectedTables'] = [];
53  if ($currentSchedulerModuleAction->equals(‪Action::ADD)) {
54  // In case of new task, select no tables by default
55  $taskInfo['scheduler_optimizeDatabaseTables_selectedTables'] = [];
56  } elseif ($currentSchedulerModuleAction->equals(‪Action::EDIT)) {
57  // In case of editing the task, set to currently selected value
58  $taskInfo['scheduler_optimizeDatabaseTables_selectedTables'] = $task->selectedTables;
59  }
60  }
61  $fieldName = 'tx_scheduler[scheduler_optimizeDatabaseTables_selectedTables][]';
62  $fieldId = 'scheduler_optimizeDatabaseTables_selectedTables';
63  $fieldOptions = $this->‪getDatabaseTableOptions($taskInfo['scheduler_optimizeDatabaseTables_selectedTables']);
64  $fieldHtml = '<select class="form-control" name="' . $fieldName
65  . '" id="' . $fieldId
66  . '" class="from-control" size="10" multiple="multiple">'
67  . $fieldOptions
68  . '</select>';
69  $additionalFields = [];
70  $additionalFields[$fieldId] = [
71  'code' => $fieldHtml,
72  'label' => $this->languageFile . ':label.optimizeDatabaseTables.selectTables',
73  'cshKey' => '_MOD_system_txschedulerM1',
74  'cshLabel' => $fieldId,
75  ];
76 
77  return $additionalFields;
78  }
79 
87  public function ‪validateAdditionalFields(array &$submittedData, ‪SchedulerModuleController $schedulerModule)
88  {
89  $validData = true;
90  $availableTables = $this->‪getOptimizableTables();
91  if (is_array($submittedData['scheduler_optimizeDatabaseTables_selectedTables'])) {
92  $invalidTables = array_diff(
93  $submittedData['scheduler_optimizeDatabaseTables_selectedTables'],
94  $availableTables
95  );
96  if (!empty($invalidTables)) {
97  $this->‪addMessage(
98  $this->‪getLanguageService()->sL($this->languageFile . ':msg.selectionOfNonExistingDatabaseTables'),
100  );
101  $validData = false;
102  }
103  } else {
104  $this->‪addMessage(
105  $this->‪getLanguageService()->sL($this->languageFile . ':msg.noDatabaseTablesSelected'),
107  );
108  $validData = false;
109  }
110 
111  return $validData;
112  }
113 
120  public function ‪saveAdditionalFields(array $submittedData, ‪AbstractTask $task)
121  {
122  $task->selectedTables = $submittedData['scheduler_optimizeDatabaseTables_selectedTables'];
123  }
124 
131  protected function ‪getDatabaseTableOptions(array $selectedTables)
132  {
133  $options = [];
134  $availableTables = $this->‪getOptimizableTables();
135  foreach ($availableTables as $tableName) {
136  $selected = in_array($tableName, $selectedTables, true) ? ' selected="selected"' : '';
137  $options[] = '<option value="' . $tableName . '"' . $selected . '>' . $tableName . '</option>';
138  }
139 
140  return implode('', $options);
141  }
142 
148  protected function ‪getOptimizableTables()
149  {
150  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
151  $defaultConnection = $connectionPool->getConnectionByName(‪ConnectionPool::DEFAULT_CONNECTION_NAME);
152 
153  // Retrieve all optimizable tables for the default connection
154  $optimizableTables = $this->‪getOptimizableTablesForConnection($defaultConnection);
155 
156  // Retrieve additional optimizable tables that have been remapped to a different connection
157  $tableMap = ‪$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'] ?? [];
158  if ($tableMap) {
159  // Remove all remapped tables from the list of optimizable tables
160  // These tables will be rechecked and possibly re-added to the list
161  // of optimizable tables. This ensures that no orphaned table from
162  // the default connection gets mistakenly labeled as optimizable.
163  $optimizableTables = array_diff($optimizableTables, array_keys($tableMap));
164 
165  // Walk each connection and check all tables that have been
166  // remapped to it for optimization support.
167  $connectionNames = array_keys(array_flip($tableMap));
168  foreach ($connectionNames as $connectionName) {
169  $connection = $connectionPool->getConnectionByName($connectionName);
170  $tablesOnConnection = array_keys(array_filter(
171  $tableMap,
172  function ($value) use ($connectionName) {
173  return $value === $connectionName;
174  }
175  ));
176  $tables = $this->‪getOptimizableTablesForConnection($connection, $tablesOnConnection);
177  $optimizableTables = array_merge($optimizableTables, $tables);
178  }
179  }
180 
181  sort($optimizableTables);
182 
183  return $optimizableTables;
184  }
185 
194  protected function ‪getOptimizableTablesForConnection(‪Connection $connection, array $tableNames = []): array
195  {
196  // Return empty list if the database platform is not MySQL
197  if (strpos($connection->‪getServerVersion(), 'MySQL') !== 0) {
198  return [];
199  }
200 
201  // Retrieve all tables from the MySQL information schema that have an engine type
202  // that supports the OPTIMIZE TABLE command.
203  $queryBuilder = $connection->‪createQueryBuilder();
204  $queryBuilder->‪select('TABLE_NAME AS Table', 'ENGINE AS Engine')
205  ->‪from('information_schema.TABLES')
206  ->‪where(
207  $queryBuilder->expr()->eq(
208  'TABLE_TYPE',
209  $queryBuilder->createNamedParameter('BASE TABLE', \PDO::PARAM_STR)
210  ),
211  $queryBuilder->expr()->in(
212  'ENGINE',
213  $queryBuilder->createNamedParameter(['InnoDB', 'MyISAM', 'ARCHIVE'], Connection::PARAM_STR_ARRAY)
214  ),
215  $queryBuilder->expr()->eq(
216  'TABLE_SCHEMA',
217  $queryBuilder->createNamedParameter($connection->getDatabase(), \PDO::PARAM_STR)
218  )
219  );
220 
221  if (!empty($tableNames)) {
222  $queryBuilder->‪andWhere(
223  $queryBuilder->expr()->in(
224  'TABLE_NAME',
225  $queryBuilder->createNamedParameter($tableNames, \PDO::PARAM_STR)
226  )
227  );
228  }
229 
230  $tables = $queryBuilder->‪execute()->fetchAll();
231 
232  return array_column($tables, 'Table');
233  }
234 
238  protected function ‪getLanguageService(): ?‪LanguageService
239  {
240  return ‪$GLOBALS['LANG'] ?? null;
241  }
242 }
‪TYPO3\CMS\Scheduler\Task\Enumeration\Action\ADD
‪const ADD
Definition: Action.php:28
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\$languageFile
‪string $languageFile
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:35
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\select
‪QueryBuilder select(string ... $selects)
Definition: QueryBuilder.php:416
‪TYPO3\CMS\Scheduler\Task
Definition: AbstractTask.php:16
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\getOptimizableTablesForConnection
‪array getOptimizableTablesForConnection(Connection $connection, array $tableNames=[])
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:193
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\getAdditionalFields
‪array getAdditionalFields(array &$taskInfo, $task, SchedulerModuleController $schedulerModule)
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:45
‪TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider
Definition: AbstractAdditionalFieldProvider.php:28
‪TYPO3\CMS\Core\Database\ConnectionPool\DEFAULT_CONNECTION_NAME
‪const DEFAULT_CONNECTION_NAME
Definition: ConnectionPool.php:50
‪TYPO3\CMS\Scheduler\AbstractAdditionalFieldProvider\addMessage
‪addMessage(string $message, int $severity=FlashMessage::OK)
Definition: AbstractAdditionalFieldProvider.php:35
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\getLanguageService
‪LanguageService null getLanguageService()
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:237
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\from
‪QueryBuilder from(string $from, string $alias=null)
Definition: QueryBuilder.php:531
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\saveAdditionalFields
‪saveAdditionalFields(array $submittedData, AbstractTask $task)
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:119
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\validateAdditionalFields
‪bool validateAdditionalFields(array &$submittedData, SchedulerModuleController $schedulerModule)
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:86
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\andWhere
‪QueryBuilder andWhere(... $where)
Definition: QueryBuilder.php:694
‪TYPO3\CMS\Scheduler\Task\AbstractTask
Definition: AbstractTask.php:35
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\getDatabaseTableOptions
‪string getDatabaseTableOptions(array $selectedTables)
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:130
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\execute
‪Statement Doctrine DBAL ForwardCompatibility Result Doctrine DBAL Driver ResultStatement int execute()
Definition: QueryBuilder.php:204
‪TYPO3\CMS\Scheduler\Controller\SchedulerModuleController
Definition: SchedulerModuleController.php:56
‪TYPO3\CMS\Core\Database\Connection\getServerVersion
‪string getServerVersion()
Definition: Connection.php:383
‪TYPO3\CMS\Scheduler\Task\Enumeration\Action\EDIT
‪const EDIT
Definition: Action.php:30
‪TYPO3\CMS\Scheduler\Controller\SchedulerModuleController\getCurrentAction
‪Action getCurrentAction()
Definition: SchedulerModuleController.php:181
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider\getOptimizableTables
‪array getOptimizableTables()
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:147
‪TYPO3\CMS\Scheduler\Task\OptimizeDatabaseTableAdditionalFieldProvider
Definition: OptimizeDatabaseTableAdditionalFieldProvider.php:32
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:36
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪TYPO3\CMS\Scheduler\Task\Enumeration\Action
Definition: Action.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Database\Connection\createQueryBuilder
‪TYPO3 CMS Core Database Query QueryBuilder createQueryBuilder()
Definition: Connection.php:117
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Database\Query\QueryBuilder\where
‪QueryBuilder where(... $predicates)
Definition: QueryBuilder.php:677
‪TYPO3\CMS\Core\Messaging\AbstractMessage\ERROR
‪const ERROR
Definition: AbstractMessage.php:31