TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ImportantActions.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Install\Controller\Action\Tool;
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 
25 use TYPO3\CMS\Install\Controller\Action;
26 
31 {
37  protected function executeAction()
38  {
39  if (isset($this->postValues['set']['changeEncryptionKey'])) {
40  $this->setNewEncryptionKeyAndLogOut();
41  }
42 
43  $actionMessages = [];
44  if (isset($this->postValues['set']['changeInstallToolPassword'])) {
45  $actionMessages[] = $this->changeInstallToolPassword();
46  }
47  if (isset($this->postValues['set']['changeSiteName'])) {
48  $actionMessages[] = $this->changeSiteName();
49  }
50  if (isset($this->postValues['set']['createAdministrator'])) {
51  $actionMessages[] = $this->createAdministrator();
52  }
53  if (isset($this->postValues['set']['clearAllCache'])) {
54  $actionMessages[] = $this->clearAllCache();
55  $actionMessages[] = $this->clearOpcodeCache();
56  }
57  if (isset($this->postValues['set']['dumpAutoload'])) {
58  $actionMessages[] = $this->dumpAutoload();
59  }
60 
61  // Database analyzer handling
62  if (isset($this->postValues['set']['databaseAnalyzerExecute'])
63  || isset($this->postValues['set']['databaseAnalyzerAnalyze'])
64  ) {
66  }
67  if (isset($this->postValues['set']['databaseAnalyzerExecute'])) {
68  $actionMessages = array_merge($actionMessages, $this->databaseAnalyzerExecute());
69  }
70  if (isset($this->postValues['set']['databaseAnalyzerAnalyze'])) {
71  try {
72  $actionMessages[] = $this->databaseAnalyzerAnalyze();
73  } catch (\TYPO3\CMS\Core\Database\Schema\Exception\StatementException $e) {
74  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
75  $message->setTitle('Database analysis failed');
76  $message->setMessage($e->getMessage());
77  $actionMessages[] = $message;
78  }
79  }
80 
81  $this->view->assign('actionMessages', $actionMessages);
82 
83  $operatingSystem = TYPO3_OS === 'WIN' ? 'Windows' : 'Unix';
84 
85  $opcodeCacheService = GeneralUtility::makeInstance(OpcodeCacheService::class);
86 
88  $coreUpdateService = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Service\CoreUpdateService::class);
89  $this->view
90  ->assign('enableCoreUpdate', $coreUpdateService->isCoreUpdateEnabled())
91  ->assign('composerMode', Bootstrap::usesComposerClassLoading())
92  ->assign('operatingSystem', $operatingSystem)
93  ->assign('cgiDetected', GeneralUtility::isRunningOnCgiServerApi())
94  ->assign('extensionCompatibilityTesterProtocolFile', GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . 'typo3temp/assets/ExtensionCompatibilityTester.txt')
95  ->assign('extensionCompatibilityTesterErrorProtocolFile', GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . 'typo3temp/assets/ExtensionCompatibilityTesterErrors.json')
96  ->assign('extensionCompatibilityTesterMessages', $this->getExtensionCompatibilityTesterMessages())
97  ->assign('listOfOpcodeCaches', $opcodeCacheService->getAllActive());
98 
99  $connectionInfos = [];
100  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
101  foreach ($connectionPool->getConnectionNames() as $connectionName) {
102  $connection = $connectionPool->getConnectionByName($connectionName);
103  $connectionParameters = $connection->getParams();
104  $connectionInfo = [
105  'connectionName' => $connectionName,
106  'version' => $connection->getServerVersion(),
107  'databaseName' => $connection->getDatabase(),
108  'username' => $connection->getUsername(),
109  'host' => $connection->getHost(),
110  'port' => $connection->getPort(),
111  'socket' => $connectionParameters['unix_socket'] ?? '',
112  'numberOfTables' => count($connection->getSchemaManager()->listTables()),
113  'numberOfMappedTables' => 0,
114  ];
115  if (isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
116  && is_array($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
117  ) {
118  // Count number of array keys having $connectionName as value
119  $connectionInfo['numberOfMappedTables'] = count(array_intersect(
120  $GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'],
121  [$connectionName]
122  ));
123  }
124  $connectionInfos[] = $connectionInfo;
125  }
126 
127  $this->view->assign('connections', $connectionInfos);
128 
129  return $this->view->render();
130  }
131 
137  protected function changeInstallToolPassword()
138  {
139  $values = $this->postValues['values'];
140  if ($values['newInstallToolPassword'] !== $values['newInstallToolPasswordCheck']) {
142  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
143  $message->setTitle('Install tool password not changed');
144  $message->setMessage('Given passwords do not match.');
145  } elseif (strlen($values['newInstallToolPassword']) < 8) {
147  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
148  $message->setTitle('Install tool password not changed');
149  $message->setMessage('Given password must be at least eight characters long.');
150  } else {
152  $configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
153  $configurationManager->setLocalConfigurationValueByPath(
154  'BE/installToolPassword',
155  $this->getHashedPassword($values['newInstallToolPassword'])
156  );
158  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
159  $message->setTitle('Install tool password changed');
160  }
161  return $message;
162  }
163 
169  protected function changeSiteName()
170  {
171  $values = $this->postValues['values'];
172  if (isset($values['newSiteName']) && $values['newSiteName'] !== '') {
174  $configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
175  $configurationManager->setLocalConfigurationValueByPath('SYS/sitename', $values['newSiteName']);
177  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
178  $message->setTitle('Site name changed');
179  $this->view->assign('siteName', $values['newSiteName']);
180  } else {
182  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
183  $message->setTitle('Site name not changed');
184  $message->setMessage('Site name must be at least one character long.');
185  }
186  return $message;
187  }
188 
194  protected function clearAllCache()
195  {
197  $clearCacheService = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Service\ClearCacheService::class);
198  $clearCacheService->clearAll();
199  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
200  $message->setTitle('Successfully cleared all caches');
201  return $message;
202  }
203 
209  protected function clearOpcodeCache()
210  {
211  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive();
212  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
213  $message->setTitle('Successfully cleared all available opcode caches');
214  return $message;
215  }
216 
222  protected function dumpAutoload(): \TYPO3\CMS\Install\Status\StatusInterface
223  {
225  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\NoticeStatus::class);
226  $message->setTitle('Skipped generating additional class loading information in composer mode.');
227  } else {
228  ClassLoadingInformation::dumpClassLoadingInformation();
229  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
230  $message->setTitle('Successfully dumped class loading information for extensions.');
231  }
232  return $message;
233  }
234 
240  protected function setNewEncryptionKeyAndLogOut()
241  {
242  $newKey = GeneralUtility::makeInstance(Random::class)->generateRandomHexString(96);
244  $configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class);
245  $configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $newKey);
248  \TYPO3\CMS\Core\FormProtection\InstallToolFormProtection::class
249  );
250  $formProtection->clean();
252  $session = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Service\SessionService::class);
253  $session->destroySession();
254  \TYPO3\CMS\Core\Utility\HttpUtility::redirect('Install.php?install[context]=' . $this->getContext());
255  }
256 
262  protected function createAdministrator()
263  {
264  $values = $this->postValues['values'];
265  $username = preg_replace('/\\s/i', '', $values['newUserUsername']);
266  $password = $values['newUserPassword'];
267  $passwordCheck = $values['newUserPasswordCheck'];
268 
269  if (strlen($username) < 1) {
271  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
272  $message->setTitle('Administrator user not created');
273  $message->setMessage('No valid username given.');
274  } elseif ($password !== $passwordCheck) {
276  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
277  $message->setTitle('Administrator user not created');
278  $message->setMessage('Passwords do not match.');
279  } elseif (strlen($password) < 8) {
281  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
282  $message->setTitle('Administrator user not created');
283  $message->setMessage('Password must be at least eight characters long.');
284  } else {
285  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
286  $userExists = $connectionPool->getConnectionForTable('be_users')
287  ->count(
288  'uid',
289  'be_users',
290  ['username' => $username]
291  );
292 
293  if ($userExists) {
295  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
296  $message->setTitle('Administrator user not created');
297  $message->setMessage('A user with username "' . $username . '" exists already.');
298  } else {
299  $hashedPassword = $this->getHashedPassword($password);
300  $adminUserFields = [
301  'username' => $username,
302  'password' => $hashedPassword,
303  'admin' => 1,
304  'tstamp' => $GLOBALS['EXEC_TIME'],
305  'crdate' => $GLOBALS['EXEC_TIME']
306  ];
307  $connectionPool->getConnectionForTable('be_users')
308  ->insert('be_users', $adminUserFields);
310  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
311  $message->setTitle('Administrator created with username "' . $username . '".');
312  }
313  }
314 
315  return $message;
316  }
317 
323  protected function databaseAnalyzerExecute()
324  {
325  $messages = [];
326 
327  // Early return in case no update was selected
328  if (empty($this->postValues['values'])) {
330  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\WarningStatus::class);
331  $message->setTitle('No database changes selected');
332  $messages[] = $message;
333  return $messages;
334  }
335 
336  $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
337  $sqlStatements = $sqlReader->getCreateTableStatementArray($sqlReader->getTablesDefinitionString());
338  $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
339 
340  $statementHashesToPerform = $this->postValues['values'];
341 
342  $results = $schemaMigrationService->migrate($sqlStatements, $statementHashesToPerform);
343 
344  // Create error flash messages if any
345  foreach ($results as $errorMessage) {
346  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\ErrorStatus::class);
347  $message->setTitle('Database update failed');
348  $message->setMessage('Error: ' . $errorMessage);
349  $messages[] = $message;
350  }
351 
352  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
353  $message->setTitle('Executed database updates');
354  $messages[] = $message;
355 
356  return $messages;
357  }
358 
372  protected function databaseAnalyzerAnalyze()
373  {
374  $databaseAnalyzerSuggestion = [];
375 
376  $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
377  $sqlStatements = $sqlReader->getCreateTableStatementArray($sqlReader->getTablesDefinitionString());
378  $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
379 
380  $addCreateChange = $schemaMigrationService->getUpdateSuggestions($sqlStatements);
381  // Aggregate the per-connection statements into one flat array
382  $addCreateChange = array_merge_recursive(...array_values($addCreateChange));
383 
384  if (isset($addCreateChange['create_table'])) {
385  $databaseAnalyzerSuggestion['addTable'] = [];
386  foreach ($addCreateChange['create_table'] as $hash => $statement) {
387  $databaseAnalyzerSuggestion['addTable'][$hash] = [
388  'hash' => $hash,
389  'statement' => $statement,
390  ];
391  }
392  }
393  if (isset($addCreateChange['add'])) {
394  $databaseAnalyzerSuggestion['addField'] = [];
395  foreach ($addCreateChange['add'] as $hash => $statement) {
396  $databaseAnalyzerSuggestion['addField'][$hash] = [
397  'hash' => $hash,
398  'statement' => $statement,
399  ];
400  }
401  }
402  if (isset($addCreateChange['change'])) {
403  $databaseAnalyzerSuggestion['change'] = [];
404  foreach ($addCreateChange['change'] as $hash => $statement) {
405  $databaseAnalyzerSuggestion['change'][$hash] = [
406  'hash' => $hash,
407  'statement' => $statement,
408  ];
409  if (isset($addCreateChange['change_currentValue'][$hash])) {
410  $databaseAnalyzerSuggestion['change'][$hash]['current'] = $addCreateChange['change_currentValue'][$hash];
411  }
412  }
413  }
414 
415  // Difference from current to expected
416  $dropRename = $schemaMigrationService->getUpdateSuggestions($sqlStatements, true);
417  // Aggregate the per-connection statements into one flat array
418  $dropRename = array_merge_recursive(...array_values($dropRename));
419  if (isset($dropRename['change_table'])) {
420  $databaseAnalyzerSuggestion['renameTableToUnused'] = [];
421  foreach ($dropRename['change_table'] as $hash => $statement) {
422  $databaseAnalyzerSuggestion['renameTableToUnused'][$hash] = [
423  'hash' => $hash,
424  'statement' => $statement,
425  ];
426  if (!empty($dropRename['tables_count'][$hash])) {
427  $databaseAnalyzerSuggestion['renameTableToUnused'][$hash]['count'] = $dropRename['tables_count'][$hash];
428  }
429  }
430  }
431  if (isset($dropRename['change'])) {
432  $databaseAnalyzerSuggestion['renameTableFieldToUnused'] = [];
433  foreach ($dropRename['change'] as $hash => $statement) {
434  $databaseAnalyzerSuggestion['renameTableFieldToUnused'][$hash] = [
435  'hash' => $hash,
436  'statement' => $statement,
437  ];
438  }
439  }
440  if (isset($dropRename['drop'])) {
441  $databaseAnalyzerSuggestion['deleteField'] = [];
442  foreach ($dropRename['drop'] as $hash => $statement) {
443  $databaseAnalyzerSuggestion['deleteField'][$hash] = [
444  'hash' => $hash,
445  'statement' => $statement,
446  ];
447  }
448  }
449  if (isset($dropRename['drop_table'])) {
450  $databaseAnalyzerSuggestion['deleteTable'] = [];
451  foreach ($dropRename['drop_table'] as $hash => $statement) {
452  $databaseAnalyzerSuggestion['deleteTable'][$hash] = [
453  'hash' => $hash,
454  'statement' => $statement,
455  ];
456  if (!empty($dropRename['tables_count'][$hash])) {
457  $databaseAnalyzerSuggestion['deleteTable'][$hash]['count'] = $dropRename['tables_count'][$hash];
458  }
459  }
460  }
461 
462  $this->view->assign('databaseAnalyzerSuggestion', $databaseAnalyzerSuggestion);
463 
465  $message = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Status\OkStatus::class);
466  $message->setTitle('Analyzed current database');
467 
468  return $message;
469  }
470 }
static redirect($url, $httpStatus=self::HTTP_STATUS_303)
Definition: HttpUtility.php:76
static get($classNameOrType= 'default',...$constructorArguments)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)