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