‪TYPO3CMS  ‪main
MaintenanceController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
23 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
48 
54 {
56 
57  public function ‪__construct(
58  private readonly ‪LateBootService $lateBootService,
59  private readonly ‪ClearCacheService $clearCacheService,
60  private readonly ConfigurationManager $configurationManager,
61  private readonly ‪PasswordHashFactory $passwordHashFactory,
62  private readonly ‪Locales $locales,
63  private readonly ‪LanguageServiceFactory $languageServiceFactory,
64  private readonly ‪FormProtectionFactory $formProtectionFactory
65  ) {
66  ‪$GLOBALS['LANG'] = $this->languageServiceFactory->create('en');
67  $passwordPolicy = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] ?? 'default';
68  $this->passwordPolicyValidator = GeneralUtility::makeInstance(
69  PasswordPolicyValidator::class,
71  is_string($passwordPolicy) ? $passwordPolicy : ''
72  );
73  }
74 
78  public function ‪cardsAction(ServerRequestInterface $request): ResponseInterface
79  {
80  $view = $this->‪initializeView($request);
81  return new ‪JsonResponse([
82  'success' => true,
83  'html' => $view->render('Maintenance/Cards'),
84  ]);
85  }
86 
90  public function ‪cacheClearAllAction(): ResponseInterface
91  {
92  $this->clearCacheService->clearAll();
93  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive();
94  $messageQueue = new ‪FlashMessageQueue('install');
95  $messageQueue->enqueue(
96  new ‪FlashMessage('Successfully cleared all caches and all available opcode caches.', 'Caches cleared')
97  );
98  return new ‪JsonResponse([
99  'success' => true,
100  'status' => $messageQueue,
101  ]);
102  }
103 
107  public function ‪clearTypo3tempFilesStatsAction(ServerRequestInterface $request): ResponseInterface
108  {
109  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables(false);
110  $typo3tempFileService = $container->get(Typo3tempFileService::class);
111 
112  $view = $this->‪initializeView($request);
113  $formProtection = $this->formProtectionFactory->createFromRequest($request);
114  $view->assignMultiple([
115  'clearTypo3tempFilesToken' => $formProtection->generateToken('installTool', 'clearTypo3tempFiles'),
116  ]);
117  return new ‪JsonResponse(
118  [
119  'success' => true,
120  'stats' => $typo3tempFileService->getDirectoryStatistics(),
121  'html' => $view->render('Maintenance/ClearTypo3tempFiles'),
122  'buttons' => [
123  [
124  'btnClass' => 'btn-default t3js-clearTypo3temp-stats',
125  'text' => 'Scan again',
126  ],
127  ],
128  ]
129  );
130  }
131 
135  public function ‪clearTypo3tempFilesAction(ServerRequestInterface $request): ResponseInterface
136  {
137  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables(false);
138  $typo3tempFileService = $container->get(Typo3tempFileService::class);
139  $messageQueue = new ‪FlashMessageQueue('install');
140  $folder = $request->getParsedBody()['install']['folder'];
141  // storageUid is an optional post param if FAL storages should be cleaned
142  $storageUid = $request->getParsedBody()['install']['storageUid'] ?? null;
143  if ($storageUid === null) {
144  $typo3tempFileService->clearAssetsFolder($folder);
145  $messageQueue->enqueue(new ‪FlashMessage('The directory "' . $folder . '" has been cleared successfully', 'Directory cleared'));
146  } else {
147  $storageUid = (int)$storageUid;
148  // We have to get the stats before deleting files, otherwise we're not able to retrieve the amount of files anymore
149  $stats = $typo3tempFileService->getStatsFromStorageByUid($storageUid);
150  $failedDeletions = $typo3tempFileService->clearProcessedFiles($storageUid);
151  if ($failedDeletions) {
152  $messageQueue->enqueue(new ‪FlashMessage(
153  'Failed to delete ' . $failedDeletions . ' processed files. See TYPO3 log (by default typo3temp/var/log/typo3_*.log)',
154  'Failed to delete files',
155  ContextualFeedbackSeverity::ERROR
156  ));
157  } else {
158  $messageQueue->enqueue(new ‪FlashMessage(
159  sprintf('Removed %d files from directory "%s"', $stats['numberOfFiles'], $stats['directory']),
160  'Deleted processed files'
161  ));
162  }
163  }
164  return new ‪JsonResponse([
165  'success' => true,
166  'status' => $messageQueue,
167  ]);
168  }
169 
173  public function ‪dumpAutoloadAction(): ResponseInterface
174  {
175  $messageQueue = new ‪FlashMessageQueue('install');
177  $messageQueue->enqueue(new ‪FlashMessage(
178  'Skipped generating additional class loading information in Composer mode.',
179  'Autoloader not dumped',
180  ContextualFeedbackSeverity::NOTICE
181  ));
182  } else {
184  $messageQueue->enqueue(new ‪FlashMessage(
185  'Successfully dumped class loading information for extensions.',
186  'Dumped autoloader'
187  ));
188  }
189  return new ‪JsonResponse([
190  'success' => true,
191  'status' => $messageQueue,
192  ]);
193  }
194 
198  public function ‪databaseAnalyzerAction(ServerRequestInterface $request): ResponseInterface
199  {
200  $view = $this->‪initializeView($request);
201  $formProtection = $this->formProtectionFactory->createFromRequest($request);
202  $view->assignMultiple([
203  'databaseAnalyzerExecuteToken' => $formProtection->generateToken('installTool', 'databaseAnalyzerExecute'),
204  ]);
205  return new ‪JsonResponse([
206  'success' => true,
207  'html' => $view->render('Maintenance/DatabaseAnalyzer'),
208  'buttons' => [
209  [
210  'btnClass' => 'btn-default t3js-databaseAnalyzer-analyze',
211  'text' => 'Run database compare again',
212  ], [
213  'btnClass' => 'btn-warning t3js-databaseAnalyzer-execute',
214  'text' => 'Apply selected changes',
215  ],
216  ],
217  ]);
218  }
219 
223  public function ‪databaseAnalyzerAnalyzeAction(ServerRequestInterface $request): ResponseInterface
224  {
225  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables();
226  $messageQueue = new ‪FlashMessageQueue('install');
227  $suggestions = [];
228  try {
229  $sqlReader = $container->get(SqlReader::class);
230  $sqlStatements = $sqlReader->getCreateTableStatementArray($sqlReader->getTablesDefinitionString());
231  $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
232  $addCreateChange = $schemaMigrationService->getUpdateSuggestions($sqlStatements);
233 
234  // Aggregate the per-connection statements into one flat array
235  $addCreateChange = array_merge_recursive(...array_values($addCreateChange));
236  if (!empty($addCreateChange['create_table'])) {
237  $suggestion = [
238  'key' => 'addTable',
239  'label' => 'Add tables',
240  'enabled' => true,
241  'children' => [],
242  ];
243  foreach ($addCreateChange['create_table'] as $hash => $statement) {
244  $suggestion['children'][] = [
245  'hash' => $hash,
246  'statement' => $statement,
247  ];
248  }
249  $suggestions[] = $suggestion;
250  }
251  if (!empty($addCreateChange['add'])) {
252  $suggestion = [
253  'key' => 'addField',
254  'label' => 'Add fields to tables',
255  'enabled' => true,
256  'children' => [],
257  ];
258  foreach ($addCreateChange['add'] as $hash => $statement) {
259  $suggestion['children'][] = [
260  'hash' => $hash,
261  'statement' => $statement,
262  ];
263  }
264  $suggestions[] = $suggestion;
265  }
266  if (!empty($addCreateChange['change'])) {
267  $suggestion = [
268  'key' => 'change',
269  'label' => 'Change fields',
270  'enabled' => false,
271  'children' => [],
272  ];
273  foreach ($addCreateChange['change'] as $hash => $statement) {
274  $child = [
275  'hash' => $hash,
276  'statement' => $statement,
277  ];
278  if (isset($addCreateChange['change_currentValue'][$hash])) {
279  $child['current'] = $addCreateChange['change_currentValue'][$hash];
280  }
281  $suggestion['children'][] = $child;
282  }
283  $suggestions[] = $suggestion;
284  }
285 
286  // Difference from current to expected
287  $dropRename = $schemaMigrationService->getUpdateSuggestions($sqlStatements, true);
288 
289  // Aggregate the per-connection statements into one flat array
290  $dropRename = array_merge_recursive(...array_values($dropRename));
291  if (!empty($dropRename['change_table'])) {
292  $suggestion = [
293  'key' => 'renameTableToUnused',
294  'label' => 'Remove tables (rename with prefix)',
295  'enabled' => false,
296  'children' => [],
297  ];
298  foreach ($dropRename['change_table'] as $hash => $statement) {
299  $child = [
300  'hash' => $hash,
301  'statement' => $statement,
302  ];
303  if (!empty($dropRename['tables_count'][$hash])) {
304  $child['rowCount'] = $dropRename['tables_count'][$hash];
305  }
306  $suggestion['children'][] = $child;
307  }
308  $suggestions[] = $suggestion;
309  }
310  if (!empty($dropRename['change'])) {
311  $suggestion = [
312  'key' => 'renameTableFieldToUnused',
313  'label' => 'Remove unused fields (rename with prefix)',
314  'enabled' => false,
315  'children' => [],
316  ];
317  foreach ($dropRename['change'] as $hash => $statement) {
318  $suggestion['children'][] = [
319  'hash' => $hash,
320  'statement' => $statement,
321  ];
322  }
323  $suggestions[] = $suggestion;
324  }
325  if (!empty($dropRename['drop'])) {
326  $suggestion = [
327  'key' => 'deleteField',
328  'label' => 'Drop fields (really!)',
329  'enabled' => false,
330  'children' => [],
331  ];
332  foreach ($dropRename['drop'] as $hash => $statement) {
333  $suggestion['children'][] = [
334  'hash' => $hash,
335  'statement' => $statement,
336  ];
337  }
338  $suggestions[] = $suggestion;
339  }
340  if (!empty($dropRename['drop_table'])) {
341  $suggestion = [
342  'key' => 'deleteTable',
343  'label' => 'Drop tables (really!)',
344  'enabled' => false,
345  'children' => [],
346  ];
347  foreach ($dropRename['drop_table'] as $hash => $statement) {
348  $child = [
349  'hash' => $hash,
350  'statement' => $statement,
351  ];
352  if (!empty($dropRename['tables_count'][$hash])) {
353  $child['rowCount'] = $dropRename['tables_count'][$hash];
354  }
355  $suggestion['children'][] = $child;
356  }
357  $suggestions[] = $suggestion;
358  }
359  } catch (‪StatementException $e) {
360  $messageQueue->enqueue(new ‪FlashMessage(
361  $e->getMessage(),
362  'Database analysis failed',
363  ContextualFeedbackSeverity::ERROR
364  ));
365  }
366  return new ‪JsonResponse([
367  'success' => true,
368  'status' => $messageQueue,
369  'suggestions' => $suggestions,
370  ]);
371  }
372 
376  public function ‪databaseAnalyzerExecuteAction(ServerRequestInterface $request): ResponseInterface
377  {
378  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables();
379  $messageQueue = new ‪FlashMessageQueue('install');
380  $selectedHashes = $request->getParsedBody()['install']['hashes'] ?? [];
381  if (empty($selectedHashes)) {
382  $messageQueue->enqueue(new ‪FlashMessage(
383  'Please select any change by activating their respective checkboxes.',
384  'No database changes selected',
385  ContextualFeedbackSeverity::WARNING
386  ));
387  } else {
388  $sqlReader = $container->get(SqlReader::class);
389  $sqlStatements = $sqlReader->getCreateTableStatementArray($sqlReader->getTablesDefinitionString());
390  $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
391  $statementHashesToPerform = array_flip($selectedHashes);
392  $results = $schemaMigrationService->migrate($sqlStatements, $statementHashesToPerform);
393  // Create error flash messages if any
394  foreach ($results as $errorMessage) {
395  $messageQueue->enqueue(new ‪FlashMessage(
396  'Error: ' . $errorMessage,
397  'Database update failed',
398  ContextualFeedbackSeverity::ERROR
399  ));
400  }
401  $messageQueue->enqueue(new ‪FlashMessage(
402  'Executed database updates',
403  'Executed database updates'
404  ));
405  }
406  return new ‪JsonResponse([
407  'success' => true,
408  'status' => $messageQueue,
409  ]);
410  }
411 
415  public function ‪clearTablesStatsAction(ServerRequestInterface $request): ResponseInterface
416  {
417  $view = $this->‪initializeView($request);
418  $formProtection = $this->formProtectionFactory->createFromRequest($request);
419  $view->assignMultiple([
420  'clearTablesClearToken' => $formProtection->generateToken('installTool', 'clearTablesClear'),
421  ]);
422  return new ‪JsonResponse([
423  'success' => true,
424  'stats' => (new ‪ClearTableService())->getTableStatistics(),
425  'html' => $view->render('Maintenance/ClearTables'),
426  'buttons' => [
427  [
428  'btnClass' => 'btn-default t3js-clearTables-stats',
429  'text' => 'Scan again',
430  ],
431  ],
432  ]);
433  }
434 
440  public function ‪clearTablesClearAction(ServerRequestInterface $request): ResponseInterface
441  {
442  $table = $request->getParsedBody()['install']['table'];
443  if (empty($table)) {
444  throw new \RuntimeException(
445  'No table name given',
446  1501944076
447  );
448  }
449  (new ‪ClearTableService())->clearSelectedTable($table);
450  $messageQueue = new ‪FlashMessageQueue('install');
451  $messageQueue->enqueue(
452  new ‪FlashMessage('The table ' . $table . ' has been cleared.', 'Table cleared')
453  );
454  return new ‪JsonResponse([
455  'success' => true,
456  'status' => $messageQueue,
457  ]);
458  }
462  public function ‪createAdminGetDataAction(ServerRequestInterface $request): ResponseInterface
463  {
464  $view = $this->‪initializeView($request);
465  $formProtection = $this->formProtectionFactory->createFromRequest($request);
466  $view->assignMultiple([
467  'createAdminToken' => $formProtection->generateToken('installTool', 'createAdmin'),
468  'passwordPolicyRequirements' => $this->passwordPolicyValidator->getRequirements(),
469  ]);
470  return new ‪JsonResponse([
471  'success' => true,
472  'html' => $view->render('Maintenance/CreateAdmin'),
473  'buttons' => [
474  [
475  'btnClass' => 'btn-default t3js-createAdmin-create',
476  'text' => 'Create administrator user',
477  ],
478  ],
479  ]);
480  }
481 
485  public function ‪createAdminAction(ServerRequestInterface $request): ResponseInterface
486  {
487  $userCreated = false;
488  $username = preg_replace('/\\s/i', '', $request->getParsedBody()['install']['userName']);
489  $password = $request->getParsedBody()['install']['userPassword'];
490  $passwordCheck = $request->getParsedBody()['install']['userPasswordCheck'];
491  $email = $request->getParsedBody()['install']['userEmail'] ?? '';
492  $realName = $request->getParsedBody()['install']['realName'] ?? '';
493  $isSystemMaintainer = ((bool)$request->getParsedBody()['install']['userSystemMaintainer'] == '1') ? true : false;
494 
495  $messages = new ‪FlashMessageQueue('install');
496  $contextData = new ‪ContextData(newUsername: $username);
497 
498  if ($username === '') {
499  $messages->enqueue(new ‪FlashMessage(
500  'No username given.',
501  'Administrator user not created',
502  ContextualFeedbackSeverity::ERROR
503  ));
504  } elseif ($password !== $passwordCheck) {
505  $messages->enqueue(new ‪FlashMessage(
506  'Passwords do not match.',
507  'Administrator user not created',
508  ContextualFeedbackSeverity::ERROR
509  ));
510  } elseif (!$this->passwordPolicyValidator->isValidPassword($password, $contextData)) {
511  $messages->enqueue(new ‪FlashMessage(
512  'The password does not meet the password policy requirements.',
513  'Administrator user not created',
514  ContextualFeedbackSeverity::ERROR
515  ));
516  } else {
517  $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
518  $userExists = $connectionPool->getConnectionForTable('be_users')
519  ->count(
520  'uid',
521  'be_users',
522  ['username' => $username]
523  );
524  if ($userExists) {
525  $messages->enqueue(new ‪FlashMessage(
526  'A user with username "' . $username . '" exists already.',
527  'Administrator user not created',
528  ContextualFeedbackSeverity::ERROR
529  ));
530  } else {
531  $hashInstance = $this->passwordHashFactory->getDefaultHashInstance('BE');
532  $hashedPassword = $hashInstance->getHashedPassword($password);
533  $adminUserFields = [
534  'username' => $username,
535  'password' => $hashedPassword,
536  'admin' => 1,
537  'realName' => $realName,
538  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
539  'crdate' => ‪$GLOBALS['EXEC_TIME'],
540  ];
541  if (GeneralUtility::validEmail($email)) {
542  $adminUserFields['email'] = $email;
543  }
544  $connectionPool->getConnectionForTable('be_users')->insert('be_users', $adminUserFields);
545  $userCreated = true;
546 
547  if ($isSystemMaintainer) {
548  // Get the new admin user uid just created
549  $newAdminUserUid = (int)$connectionPool->getConnectionForTable('be_users')->lastInsertId('be_users');
550 
551  // Get the list of the existing systemMaintainer
552  $existingSystemMaintainersList = ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['systemMaintainers'] ?? [];
553 
554  // Add the new admin user to the existing systemMaintainer list
555  $newSystemMaintainersList = $existingSystemMaintainersList;
556  $newSystemMaintainersList[] = $newAdminUserUid;
557 
558  // Update the system/settings.php file with the new list
559  $this->configurationManager->setLocalConfigurationValuesByPathValuePairs(
560  ['SYS/systemMaintainers' => $newSystemMaintainersList]
561  );
562  }
563 
564  $messages->enqueue(new ‪FlashMessage(
565  'Administrator created',
566  'An administrator with username "' . $username . '" has been created successfully.'
567  ));
568  }
569  }
570  return new ‪JsonResponse([
571  'success' => true,
572  'status' => $messages,
573  'userCreated' => $userCreated,
574  ]);
575  }
576 
582  public function ‪languagePacksGetDataAction(ServerRequestInterface $request): ResponseInterface
583  {
584  $view = $this->‪initializeView($request);
585  $formProtection = $this->formProtectionFactory->createFromRequest($request);
586  $view->assignMultiple([
587  'languagePacksActivateLanguageToken' => $formProtection->generateToken('installTool', 'languagePacksActivateLanguage'),
588  'languagePacksDeactivateLanguageToken' => $formProtection->generateToken('installTool', 'languagePacksDeactivateLanguage'),
589  'languagePacksUpdatePackToken' => $formProtection->generateToken('installTool', 'languagePacksUpdatePack'),
590  'languagePacksUpdateIsoTimesToken' => $formProtection->generateToken('installTool', 'languagePacksUpdateIsoTimes'),
591  ]);
592  // This action needs TYPO3_CONF_VARS for full GeneralUtility::getUrl() config
593  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables(false, true);
594  $languagePackService = $container->get(LanguagePackService::class);
595  $extensions = $languagePackService->getExtensionLanguagePackDetails();
596  $extensionList = array_map(function (array $extension) {
597  $extension['packs'] = array_values($extension['packs']);
598  return $extension;
599  }, array_values($extensions));
600  return new ‪JsonResponse([
601  'success' => true,
602  'languages' => $languagePackService->getLanguageDetails(),
603  'extensions' => $extensionList,
604  'activeLanguages' => $languagePackService->getActiveLanguages(),
605  'activeExtensions' => array_column($extensions, 'key'),
606  'html' => $view->render('Maintenance/LanguagePacks'),
607  ]);
608  }
609 
613  public function ‪languagePacksActivateLanguageAction(ServerRequestInterface $request): ResponseInterface
614  {
615  $messageQueue = new ‪FlashMessageQueue('install');
616  $languagePackService = GeneralUtility::makeInstance(LanguagePackService::class);
617  $availableLanguages = $languagePackService->getAvailableLanguages();
618  $activeLanguages = $languagePackService->getActiveLanguages();
619  $iso = $request->getParsedBody()['install']['iso'];
620  $activateArray = [];
621  foreach ($availableLanguages as $availableIso => $name) {
622  if ($availableIso === $iso && !in_array($availableIso, $activeLanguages, true)) {
623  $activateArray[] = $iso;
624  $dependencies = $this->locales->getLocaleDependencies($availableIso);
625  if (!empty($dependencies)) {
626  foreach ($dependencies as $dependency) {
627  if (!in_array($dependency, $activeLanguages, true)) {
628  $activateArray[] = $dependency;
629  }
630  }
631  }
632  }
633  }
634  if (!empty($activateArray)) {
635  $activeLanguages = array_merge($activeLanguages, $activateArray);
636  sort($activeLanguages);
637  $this->configurationManager->setLocalConfigurationValueByPath(
638  'EXTCONF/lang',
639  ['availableLanguages' => $activeLanguages]
640  );
641  $activationArray = [];
642  foreach ($activateArray as $activateIso) {
643  $activationArray[] = $availableLanguages[$activateIso] . ' (' . $activateIso . ')';
644  }
645  $messageQueue->enqueue(
646  new ‪FlashMessage(
647  'These languages have been activated: ' . implode(', ', $activationArray)
648  )
649  );
650  } else {
651  $messageQueue->enqueue(
652  new ‪FlashMessage('Language with ISO code "' . $iso . '" not found or already active.', '', ContextualFeedbackSeverity::ERROR)
653  );
654  }
655  return new ‪JsonResponse([
656  'success' => true,
657  'status' => $messageQueue,
658  ]);
659  }
660 
666  public function ‪languagePacksDeactivateLanguageAction(ServerRequestInterface $request): ResponseInterface
667  {
668  $messageQueue = new ‪FlashMessageQueue('install');
669  $languagePackService = GeneralUtility::makeInstance(LanguagePackService::class);
670  $availableLanguages = $languagePackService->getAvailableLanguages();
671  $activeLanguages = $languagePackService->getActiveLanguages();
672  $iso = $request->getParsedBody()['install']['iso'];
673  if (empty($iso)) {
674  throw new \RuntimeException('No iso code given', 1520109807);
675  }
676  $otherActiveLanguageDependencies = [];
677  foreach ($activeLanguages as $activeLanguage) {
678  if ($activeLanguage === $iso) {
679  continue;
680  }
681  $dependencies = $this->locales->getLocaleDependencies($activeLanguage);
682  if (in_array($iso, $dependencies, true)) {
683  $otherActiveLanguageDependencies[] = $activeLanguage;
684  }
685  }
686  if (!empty($otherActiveLanguageDependencies)) {
687  // Error: Must disable dependencies first
688  $dependentArray = [];
689  foreach ($otherActiveLanguageDependencies as $dependency) {
690  $dependentArray[] = $availableLanguages[$dependency] . ' (' . $dependency . ')';
691  }
692  $messageQueue->enqueue(
693  new ‪FlashMessage(
694  'Language "' . $availableLanguages[$iso] . ' (' . $iso . ')" can not be deactivated. These'
695  . ' other languages depend on it and need to be deactivated before:'
696  . implode(', ', $dependentArray),
697  '',
698  ContextualFeedbackSeverity::ERROR
699  )
700  );
701  } else {
702  if (in_array($iso, $activeLanguages, true)) {
703  // Deactivate this language
704  $newActiveLanguages = [];
705  foreach ($activeLanguages as $activeLanguage) {
706  if ($activeLanguage === $iso) {
707  continue;
708  }
709  $newActiveLanguages[] = $activeLanguage;
710  }
711  $this->configurationManager->setLocalConfigurationValueByPath(
712  'EXTCONF/lang',
713  ['availableLanguages' => $newActiveLanguages]
714  );
715  $messageQueue->enqueue(
716  new ‪FlashMessage(
717  'Language "' . $availableLanguages[$iso] . ' (' . $iso . ')" has been deactivated'
718  )
719  );
720  } else {
721  $messageQueue->enqueue(
722  new ‪FlashMessage(
723  'Language "' . $availableLanguages[$iso] . ' (' . $iso . ')" has not been deactivated',
724  '',
725  ContextualFeedbackSeverity::ERROR
726  )
727  );
728  }
729  }
730  return new ‪JsonResponse([
731  'success' => true,
732  'status' => $messageQueue,
733  ]);
734  }
735 
741  public function ‪languagePacksUpdatePackAction(ServerRequestInterface $request): ResponseInterface
742  {
743  $container = $this->lateBootService->loadExtLocalconfDatabaseAndExtTables(false, true);
744  $iso = $request->getParsedBody()['install']['iso'];
745  $key = $request->getParsedBody()['install']['extension'];
746 
747  $languagePackService = $container->get(LanguagePackService::class);
748 
749  return new ‪JsonResponse([
750  'success' => true,
751  'packResult' => $languagePackService->languagePackDownload($key, $iso),
752  ]);
753  }
754 
758  public function ‪languagePacksUpdateIsoTimesAction(ServerRequestInterface $request): ResponseInterface
759  {
760  $isos = $request->getParsedBody()['install']['isos'];
761  $languagePackService = GeneralUtility::makeInstance(LanguagePackService::class);
762  $languagePackService->setLastUpdatedIsoCode($isos);
763 
764  // The cache manager is already instantiated in the install tool
765  // with some hacked settings to disable caching of extbase and fluid.
766  // We want a "fresh" object here to operate on a different cache setup.
767  // cacheManager implements SingletonInterface, so the only way to get a "fresh"
768  // instance is by circumventing makeInstance and using new directly!
769  $cacheManager = new ‪CacheManager();
770  $cacheManager->setCacheConfigurations(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
771  $cacheManager->getCache('l10n')->flush();
772 
773  return new ‪JsonResponse(['success' => true]);
774  }
775 
779  public function ‪resetBackendUserUcAction(): ResponseInterface
780  {
781  GeneralUtility::makeInstance(ConnectionPool::class)
782  ->getQueryBuilderForTable('be_users')
783  ->update('be_users')
784  ->set('uc', '')
785  ->executeStatement();
786  $messageQueue = new ‪FlashMessageQueue('install');
787  $messageQueue->enqueue(new ‪FlashMessage(
788  'Preferences of all backend users have been reset',
789  'Reset preferences of all backend users'
790  ));
791  return new ‪JsonResponse([
792  'success' => true,
793  'status' => $messageQueue,
794  ]);
795  }
796 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Core\Database\Schema\Exception\StatementException
Definition: StatementException.php:24
‪TYPO3\CMS\Install\Controller\MaintenanceController\clearTypo3tempFilesAction
‪clearTypo3tempFilesAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:135
‪TYPO3\CMS\Install\Controller\MaintenanceController\clearTablesClearAction
‪clearTablesClearAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:440
‪TYPO3\CMS\Core\Core\Environment\isComposerMode
‪static isComposerMode()
Definition: Environment.php:137
‪TYPO3\CMS\Install\Controller\MaintenanceController\createAdminGetDataAction
‪createAdminGetDataAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:462
‪TYPO3\CMS\Core\Core\ClassLoadingInformation\dumpClassLoadingInformation
‪static dumpClassLoadingInformation()
Definition: ClassLoadingInformation.php:89
‪TYPO3\CMS\Install\Service\Typo3tempFileService
Definition: Typo3tempFileService.php:32
‪TYPO3\CMS\Core\Core\ClassLoadingInformation
Definition: ClassLoadingInformation.php:35
‪TYPO3\CMS\Install\Controller\MaintenanceController\__construct
‪__construct(private readonly LateBootService $lateBootService, private readonly ClearCacheService $clearCacheService, private readonly ConfigurationManager $configurationManager, private readonly PasswordHashFactory $passwordHashFactory, private readonly Locales $locales, private readonly LanguageServiceFactory $languageServiceFactory, private readonly FormProtectionFactory $formProtectionFactory)
Definition: MaintenanceController.php:57
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Install\Controller\MaintenanceController\languagePacksUpdatePackAction
‪languagePacksUpdatePackAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:741
‪TYPO3\CMS\Core\Database\Schema\SqlReader
Definition: SqlReader.php:31
‪TYPO3\CMS\Install\Controller\MaintenanceController\cardsAction
‪cardsAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:78
‪TYPO3\CMS\Install\Controller\MaintenanceController\languagePacksDeactivateLanguageAction
‪languagePacksDeactivateLanguageAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:666
‪TYPO3\CMS\Core\Database\Schema\SchemaMigrator
Definition: SchemaMigrator.php:40
‪TYPO3\CMS\Install\Service\ClearTableService
Definition: ClearTableService.php:29
‪TYPO3\CMS\Install\Controller\MaintenanceController\languagePacksUpdateIsoTimesAction
‪languagePacksUpdateIsoTimesAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:758
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Install\Controller\MaintenanceController\languagePacksGetDataAction
‪languagePacksGetDataAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:582
‪TYPO3\CMS\Install\Controller
Definition: AbstractController.php:18
‪TYPO3\CMS\Core\PasswordPolicy\NEW_USER_PASSWORD
‪@ NEW_USER_PASSWORD
Definition: PasswordPolicyAction.php:27
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator
Definition: PasswordPolicyValidator.php:29
‪TYPO3\CMS\Install\Controller\MaintenanceController\clearTablesStatsAction
‪clearTablesStatsAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:415
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Install\Controller\MaintenanceController\databaseAnalyzerExecuteAction
‪databaseAnalyzerExecuteAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:376
‪TYPO3\CMS\Install\Service\LateBootService
Definition: LateBootService.php:27
‪TYPO3\CMS\Core\Service\OpcodeCacheService
Definition: OpcodeCacheService.php:27
‪TYPO3\CMS\Install\Controller\AbstractController\initializeView
‪initializeView(ServerRequestInterface $request)
Definition: AbstractController.php:39
‪TYPO3\CMS\Install\Service\LanguagePackService
Definition: LanguagePackService.php:44
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:27
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:44
‪TYPO3\CMS\Install\Controller\MaintenanceController\clearTypo3tempFilesStatsAction
‪clearTypo3tempFilesStatsAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:107
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:28
‪TYPO3\CMS\Install\Controller\MaintenanceController\createAdminAction
‪createAdminAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:485
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Install\Controller\MaintenanceController\resetBackendUserUcAction
‪resetBackendUserUcAction()
Definition: MaintenanceController.php:779
‪TYPO3\CMS\Install\Controller\MaintenanceController
Definition: MaintenanceController.php:54
‪TYPO3\CMS\Install\Controller\AbstractController
Definition: AbstractController.php:35
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction
‪PasswordPolicyAction
Definition: PasswordPolicyAction.php:24
‪TYPO3\CMS\Install\Controller\MaintenanceController\languagePacksActivateLanguageAction
‪languagePacksActivateLanguageAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:613
‪TYPO3\CMS\Install\Controller\MaintenanceController\cacheClearAllAction
‪cacheClearAllAction()
Definition: MaintenanceController.php:90
‪TYPO3\CMS\Install\Controller\MaintenanceController\$passwordPolicyValidator
‪PasswordPolicyValidator $passwordPolicyValidator
Definition: MaintenanceController.php:55
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:51
‪TYPO3\CMS\Install\Controller\MaintenanceController\dumpAutoloadAction
‪dumpAutoloadAction()
Definition: MaintenanceController.php:173
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:30
‪TYPO3\CMS\Install\Service\ClearCacheService
Definition: ClearCacheService.php:29
‪TYPO3\CMS\Install\Controller\MaintenanceController\databaseAnalyzerAnalyzeAction
‪databaseAnalyzerAnalyzeAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:223
‪TYPO3\CMS\Install\Controller\MaintenanceController\databaseAnalyzerAction
‪databaseAnalyzerAction(ServerRequestInterface $request)
Definition: MaintenanceController.php:198
‪TYPO3\CMS\Core\PasswordPolicy\Validator\Dto\ContextData
Definition: ContextData.php:28