‪TYPO3CMS  ‪main
InstallUtility.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 
18 use Psr\EventDispatcher\EventDispatcherInterface;
19 use Psr\Log\LoggerAwareInterface;
20 use Psr\Log\LoggerAwareTrait;
21 use Symfony\Component\Finder\Finder;
36 use TYPO3\CMS\Core\Package\PackageManager;
50 
56 class ‪InstallUtility implements LoggerAwareInterface
57 {
58  use LoggerAwareTrait;
59 
61 
62  public function ‪__construct(
63  private readonly EventDispatcherInterface $eventDispatcher,
64  private readonly ‪FileHandlingUtility $fileHandlingUtility,
65  private readonly ‪ListUtility $listUtility,
66  private readonly PackageManager $packageManager,
67  private readonly ‪CacheManager $cacheManager,
68  private readonly ‪Registry $registry,
69  private readonly ‪BootService $bootService,
70  private readonly ‪OpcodeCacheService $opcodeCacheService,
71  private readonly ‪SqlReader $sqlReader,
72  private readonly ‪SchemaMigrator $schemaMigrator,
73  private readonly ‪ExtensionConfiguration $extensionConfiguration,
74  ‪LanguageServiceFactory $languageServiceFactory,
75  ) {
76  $this->languageService = $languageServiceFactory->‪createFromUserPreferences(‪$GLOBALS['BE_USER'] ?? null);
77  }
78 
82  public function ‪install(string ...$extensionKeys): void
83  {
84  foreach ($extensionKeys as $extensionKey) {
85  $this->packageManager->activatePackage($extensionKey);
86  $this->extensionConfiguration->synchronizeExtConfTemplateWithLocalConfiguration($extensionKey);
87  }
88  $this->cacheManager->flushCaches();
89  // Load a new container as we are reloading ext_localconf.php files
90  $container = $this->bootService->getContainer(false);
91  $backup = $this->bootService->makeCurrent($container);
92  // Reload cache files and Typo3LoadedExtensions
93  $this->opcodeCacheService->clearAllActive();
97  $this->‪updateDatabase();
98  foreach ($extensionKeys as $extensionKey) {
99  $this->‪processExtensionSetup($extensionKey);
100  $container->get(EventDispatcherInterface::class)->dispatch(new ‪AfterPackageActivationEvent($extensionKey, 'typo3-cms-extension', $this));
101  }
102  // Reset to the original container instance
103  $this->bootService->makeCurrent(null, $backup);
104  }
105 
106  public function ‪processExtensionSetup(string $extensionKey): void
107  {
108  $packagePath = $this->packageManager->getPackage($extensionKey)->getPackagePath();
109  $this->‪importInitialFiles($packagePath, $extensionKey);
110  $this->‪importStaticSqlFile($extensionKey, $packagePath);
111  $import = $this->‪importT3DFile($extensionKey, $packagePath);
112  $this->‪importSiteConfiguration($extensionKey, $packagePath, $import);
113  }
114 
120  public function ‪uninstall(string $extensionKey): void
121  {
122  $dependentExtensions = $this->‪findInstalledExtensionsThatDependOnExtension($extensionKey);
123  if (!empty($dependentExtensions)) {
125  sprintf(
126  $this->languageService->sL(
127  'LLL:EXT:extensionmanager/Resources/Private/Language/locallang.xlf:extensionList.uninstall.dependencyError'
128  ),
129  $extensionKey,
130  implode(', ', $dependentExtensions)
131  ),
132  1342554622
133  );
134  }
135  $this->packageManager->deactivatePackage($extensionKey);
136  $this->eventDispatcher->dispatch(new ‪AfterPackageDeactivationEvent($extensionKey, 'typo3-cms-extension', $this));
137  $this->cacheManager->flushCachesInGroup('system');
138  }
139 
143  public function ‪reloadAvailableExtensions(): void
144  {
145  $this->listUtility->reloadAvailableExtensions();
146  }
147 
151  public function ‪isAvailable(string $extensionKey): bool
152  {
153  return $this->packageManager->isPackageAvailable($extensionKey);
154  }
155 
161  public function ‪reloadPackageInformation(string $extensionKey): void
162  {
163  if ($this->packageManager->isPackageAvailable($extensionKey)) {
164  $this->opcodeCacheService->clearAllActive();
165  $this->packageManager->reloadPackageInformation($extensionKey);
166  }
167  }
168 
174  public function ‪enrichExtensionWithDetails(string $extensionKey, bool $loadTerInformation = true): array
175  {
176  $extension = $this->‪getExtensionArray($extensionKey);
177  if (!$loadTerInformation) {
178  $availableAndInstalledExtensions = $this->listUtility->enrichExtensionsWithEmConfInformation([$extensionKey => $extension]);
179  } else {
180  $availableAndInstalledExtensions = $this->listUtility->enrichExtensionsWithEmConfAndTerInformation([$extensionKey => $extension]);
181  }
182  if (!isset($availableAndInstalledExtensions[$extensionKey])) {
184  'Please check your uploaded extension "' . $extensionKey . '". The configuration file "ext_emconf.php" seems to be invalid.',
185  1391432222
186  );
187  }
188  return $availableAndInstalledExtensions[$extensionKey];
189  }
190 
195  public function ‪updateDatabase(): void
196  {
197  $sqlStatements = [];
198  $sqlStatements[] = $this->sqlReader->getTablesDefinitionString();
199  $sqlStatements = $this->sqlReader->getCreateTableStatementArray(implode(LF . LF, array_filter($sqlStatements)));
200  $updateStatements = $this->schemaMigrator->getUpdateSuggestions($sqlStatements);
201  $updateStatements = array_merge_recursive(...array_values($updateStatements));
202  $selectedStatements = [];
203  foreach (['add', 'change', 'create_table', 'change_table'] as $action) {
204  if (empty($updateStatements[$action])) {
205  continue;
206  }
207  $statements = array_combine(array_keys($updateStatements[$action]), array_fill(0, count($updateStatements[$action]), true));
208  $selectedStatements = array_merge(
209  $selectedStatements,
210  $statements
211  );
212  }
213  $this->schemaMigrator->migrate($sqlStatements, $selectedStatements);
214  }
215 
219  public function ‪removeExtension(string $extension): void
220  {
221  $absolutePath = $this->‪enrichExtensionWithDetails($extension)['packagePath'];
222  if ($this->‪isValidExtensionPath($absolutePath)) {
223  if ($this->packageManager->isPackageAvailable($extension)) {
224  // Package manager deletes the extension and removes the entry from PackageStates.php
225  $this->packageManager->deletePackage($extension);
226  } else {
227  // The extension is not listed in PackageStates.php, we can safely remove it
228  $this->fileHandlingUtility->removeDirectory($absolutePath);
229  }
230  } else {
231  throw new ‪ExtensionManagerException('No valid extension path given.', 1342875724);
232  }
233  }
234 
240  protected function ‪findInstalledExtensionsThatDependOnExtension(string $extensionKey): array
241  {
242  $availableAndInstalledExtensions = $this->listUtility->getAvailableAndInstalledExtensionsWithAdditionalInformation();
243  $dependentExtensions = [];
244  foreach ($availableAndInstalledExtensions as $availableAndInstalledExtensionKey => $availableAndInstalledExtension) {
245  if (isset($availableAndInstalledExtension['installed']) && $availableAndInstalledExtension['installed'] === true) {
246  if (is_array($availableAndInstalledExtension['constraints'] ?? false)
247  && is_array($availableAndInstalledExtension['constraints']['depends'])
248  && array_key_exists($extensionKey, $availableAndInstalledExtension['constraints']['depends'])
249  ) {
250  $dependentExtensions[] = $availableAndInstalledExtensionKey;
251  }
252  }
253  }
254  return $dependentExtensions;
255  }
256 
260  protected function ‪getExtensionArray(string $extensionKey): array
261  {
262  $availableExtensions = $this->listUtility->getAvailableExtensions();
263  if (isset($availableExtensions[$extensionKey])) {
264  return $availableExtensions[$extensionKey];
265  }
266  throw new ‪ExtensionManagerException('Extension ' . $extensionKey . ' is not available', 1342864081);
267  }
268 
273  protected function ‪importT3DFile(string $extensionKey, string $packagePath): ?‪Import
274  {
275  $extensionSiteRelPath = ‪PathUtility::stripPathSitePrefix($packagePath);
276  $registryKeysToCheck = [
277  $extensionSiteRelPath . 'Initialisation/data.t3d',
278  $extensionSiteRelPath . 'Initialisation/dataImported',
279  ];
280  foreach ($registryKeysToCheck as $registryKeyToCheck) {
281  if ($this->registry->get('extensionDataImport', $registryKeyToCheck)) {
282  // Data was imported before -> early return
283  return null;
284  }
285  }
286  $importFileToUse = null;
287  $possibleImportFiles = [
288  $packagePath . 'Initialisation/data.t3d',
289  $packagePath . 'Initialisation/data.xml',
290  ];
291  foreach ($possibleImportFiles as $possibleImportFile) {
292  if (!file_exists($possibleImportFile)) {
293  continue;
294  }
295  $importFileToUse = $possibleImportFile;
296  }
297  if ($importFileToUse !== null) {
298  // @todo: Not using service injection here since ext:impexp may not be loaded?
299  // Needs more investigation. This dependency is unfortunate in general.
300  $importExportUtility = GeneralUtility::makeInstance(ImportExportUtility::class);
301  try {
302  $importResult = $importExportUtility->importT3DFile($importFileToUse, 0);
303  $this->registry->set('extensionDataImport', $extensionSiteRelPath . 'Initialisation/dataImported', 1);
304  $this->eventDispatcher->dispatch(new ‪AfterExtensionDatabaseContentHasBeenImportedEvent($extensionKey, $importFileToUse, $importResult, $this));
305  return $importExportUtility->getImport();
306  } catch (\ErrorException $e) {
307  $this->logger->warning($e->getMessage(), ['exception' => $e]);
308  }
309  }
310  return null;
311  }
312 
317  protected function ‪importStaticSqlFile(string $extensionKey, string $packagePath): void
318  {
319  $extTablesStaticSqlFile = $packagePath . 'ext_tables_static+adt.sql';
320  $extTablesStaticSqlRelFile = ‪PathUtility::stripPathSitePrefix($extTablesStaticSqlFile);
321  if (!$this->registry->get('extensionDataImport', $extTablesStaticSqlRelFile)) {
322  $shortFileHash = '';
323  if (file_exists($extTablesStaticSqlFile)) {
324  $extTablesStaticSqlContent = (string)file_get_contents($extTablesStaticSqlFile);
325  $shortFileHash = md5($extTablesStaticSqlContent);
326  $statements = $this->sqlReader->getStatementArray($extTablesStaticSqlContent);
327  $this->schemaMigrator->importStaticData($statements, true);
328  }
329  $this->registry->set('extensionDataImport', $extTablesStaticSqlRelFile, $shortFileHash);
330  $this->eventDispatcher->dispatch(new ‪AfterExtensionStaticDatabaseContentHasBeenImportedEvent($extensionKey, $extTablesStaticSqlFile, $this));
331  }
332  }
333 
340  protected function ‪importInitialFiles(string $packagePath, string $extensionKey): void
341  {
342  $importFolder = $packagePath . 'Initialisation/Files';
343  $importRelFolder = ‪PathUtility::stripPathSitePrefix($importFolder);
344  if (!$this->registry->get('extensionDataImport', $importRelFolder)) {
345  if (file_exists($importFolder)) {
346  $destinationAbsolutePath = GeneralUtility::getFileAbsFileName(‪$GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] . $extensionKey);
347  if (!file_exists($destinationAbsolutePath) &&
348  GeneralUtility::isAllowedAbsPath($destinationAbsolutePath)
349  ) {
350  ‪GeneralUtility::mkdir($destinationAbsolutePath);
351  }
352  GeneralUtility::copyDirectory($importFolder, $destinationAbsolutePath);
353  $this->registry->set('extensionDataImport', $importRelFolder, 1);
354  $this->eventDispatcher->dispatch(new ‪AfterExtensionFilesHaveBeenImportedEvent($extensionKey, $destinationAbsolutePath, $this));
355  }
356  }
357  }
358 
359  protected function ‪importSiteConfiguration(string $extensionKey, string $packagePath, ‪Import $import = null): void
360  {
361  $importAbsFolder = $packagePath . 'Initialisation/Site';
362  $destinationFolder = ‪Environment::getConfigPath() . '/sites';
363  if (!is_dir($importAbsFolder)) {
364  return;
365  }
366  $siteConfiguration = GeneralUtility::makeInstance(SiteConfiguration::class);
367  $existingSites = $siteConfiguration->resolveAllExistingSites(false);
368  ‪GeneralUtility::mkdir($destinationFolder);
369  // @todo: Get rid of symfony finder here: We should use low level tools
370  // here to locate such files.
371  ‪$finder = GeneralUtility::makeInstance(Finder::class);
372  ‪$finder->directories()->in($importAbsFolder);
373  if (‪$finder->hasResults()) {
374  foreach (‪$finder as $siteConfigDirectory) {
375  ‪$siteIdentifier = $siteConfigDirectory->getBasename();
376  if (isset($existingSites[‪$siteIdentifier])) {
377  $this->logger->warning('Skipped importing site configuration from {key} due to existing site identifier {site}', [
378  'key' => $extensionKey,
379  'site' => ‪$siteIdentifier,
380  ]);
381  continue;
382  }
383  $targetDir = $destinationFolder . '/' . ‪$siteIdentifier;
384  if (!$this->registry->get('siteConfigImport', ‪$siteIdentifier) && !is_dir($targetDir)) {
385  ‪GeneralUtility::mkdir($targetDir);
386  GeneralUtility::copyDirectory($siteConfigDirectory->getPathname(), $targetDir);
387  $this->registry->set('siteConfigImport', ‪$siteIdentifier, 1);
388  }
389  }
390  }
391  $newSites = array_diff_key($siteConfiguration->resolveAllExistingSites(false), $existingSites);
392  $importedPages = [];
393  if ($import instanceof ‪Import) {
394  $importedPages = $import->getImportMapId()['pages'] ?? null;
395  }
396  $newSiteIdentifierList = [];
397  foreach ($newSites as $newSite) {
398  $exportedPageId = $newSite->getRootPageId();
399  ‪$siteIdentifier = $newSite->getIdentifier();
400  $newSiteIdentifierList[] = ‪$siteIdentifier;
401  $importedPageId = $importedPages[$exportedPageId] ?? null;
402  if ($importedPageId === null) {
403  $this->logger->warning('Imported site configuration with identifier {site} could not be mapped to imported page id', [
404  'site' => ‪$siteIdentifier,
405  ]);
406  continue;
407  }
408  $configuration = $siteConfiguration->load(‪$siteIdentifier);
409  $configuration['rootPageId'] = $importedPageId;
410  try {
411  $siteConfiguration->write(‪$siteIdentifier, $configuration);
413  $this->logger->warning(
414  sprintf(
415  'Imported site configuration with identifier %s could not be written: %s',
416  $newSite->getIdentifier(),
417  $e->getMessage()
418  )
419  );
420  continue;
421  }
422  }
423  $this->eventDispatcher->dispatch(new ‪AfterExtensionSiteFilesHaveBeenImportedEvent($extensionKey, $newSiteIdentifierList));
424  }
425 
431  protected function ‪isValidExtensionPath(string $path): bool
432  {
433  $allowedPaths = ‪Extension::returnInstallPaths();
434  foreach ($allowedPaths as $allowedPath) {
435  if (str_starts_with($path, $allowedPath)) {
436  return true;
437  }
438  }
439  return false;
440  }
441 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\isAvailable
‪isAvailable(string $extensionKey)
Definition: InstallUtility.php:151
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static stripPathSitePrefix(string $path)
Definition: PathUtility.php:428
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Configuration\Exception\SiteConfigurationWriteException
Definition: SiteConfigurationWriteException.php:28
‪TYPO3\CMS\Extensionmanager\Utility
Definition: DependencyUtility.php:16
‪$finder
‪if(PHP_SAPI !=='cli') $finder
Definition: header-comment.php:22
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\findInstalledExtensionsThatDependOnExtension
‪findInstalledExtensionsThatDependOnExtension(string $extensionKey)
Definition: InstallUtility.php:240
‪TYPO3\CMS\Extensionmanager\Event\AfterExtensionStaticDatabaseContentHasBeenImportedEvent
Definition: AfterExtensionStaticDatabaseContentHasBeenImportedEvent.php:26
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension
Definition: Extension.php:28
‪TYPO3\CMS\Core\Configuration\ExtensionConfiguration
Definition: ExtensionConfiguration.php:47
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\importT3DFile
‪importT3DFile(string $extensionKey, string $packagePath)
Definition: InstallUtility.php:273
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\enrichExtensionWithDetails
‪enrichExtensionWithDetails(string $extensionKey, bool $loadTerInformation=true)
Definition: InstallUtility.php:174
‪TYPO3\CMS\Core\Registry
Definition: Registry.php:33
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtLocalconf
‪static loadExtLocalconf(bool $allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1169
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\importInitialFiles
‪importInitialFiles(string $packagePath, string $extensionKey)
Definition: InstallUtility.php:340
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\getExtensionArray
‪getExtensionArray(string $extensionKey)
Definition: InstallUtility.php:260
‪TYPO3\CMS\Extensionmanager\Event\AfterExtensionSiteFilesHaveBeenImportedEvent
Definition: AfterExtensionSiteFilesHaveBeenImportedEvent.php:24
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\$languageService
‪LanguageService $languageService
Definition: InstallUtility.php:60
‪TYPO3\CMS\Core\Database\Schema\SqlReader
Definition: SqlReader.php:31
‪TYPO3\CMS\Extensionmanager\Utility\ListUtility
Definition: ListUtility.php:40
‪TYPO3\CMS\Extensionmanager\Event\AfterExtensionDatabaseContentHasBeenImportedEvent
Definition: AfterExtensionDatabaseContentHasBeenImportedEvent.php:26
‪TYPO3\CMS\Core\Core\BootService
Definition: BootService.php:32
‪TYPO3\CMS\Core\Configuration\SiteConfiguration
Definition: SiteConfiguration.php:47
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\install
‪install(string ... $extensionKeys)
Definition: InstallUtility.php:82
‪TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
Definition: FileHandlingUtility.php:38
‪TYPO3\CMS\Core\Database\Schema\SchemaMigrator
Definition: SchemaMigrator.php:39
‪TYPO3\CMS\Core\Core\Environment\getConfigPath
‪static getConfigPath()
Definition: Environment.php:212
‪TYPO3\CMS\Core\Core\Bootstrap\loadBaseTca
‪static loadBaseTca(bool $allowCaching=true, FrontendInterface $coreCache=null)
Definition: Bootstrap.php:492
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:40
‪TYPO3\CMS\Impexp\Utility\ImportExportUtility
Definition: ImportExportUtility.php:33
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility
Definition: InstallUtility.php:57
‪TYPO3\CMS\Extensionmanager\Event\AfterExtensionFilesHaveBeenImportedEvent
Definition: AfterExtensionFilesHaveBeenImportedEvent.php:26
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\processExtensionSetup
‪processExtensionSetup(string $extensionKey)
Definition: InstallUtility.php:106
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\reloadPackageInformation
‪reloadPackageInformation(string $extensionKey)
Definition: InstallUtility.php:161
‪TYPO3\CMS\Impexp\Import
Definition: Import.php:50
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\uninstall
‪uninstall(string $extensionKey)
Definition: InstallUtility.php:120
‪TYPO3\CMS\Core\Package\Event\AfterPackageActivationEvent
Definition: AfterPackageActivationEvent.php:24
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\reloadAvailableExtensions
‪reloadAvailableExtensions()
Definition: InstallUtility.php:143
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
Definition: ExtensionManagerException.php:24
‪TYPO3\CMS\Core\Service\OpcodeCacheService
Definition: OpcodeCacheService.php:27
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\isValidExtensionPath
‪isValidExtensionPath(string $path)
Definition: InstallUtility.php:431
‪TYPO3\CMS\Core\Package\Event\AfterPackageDeactivationEvent
Definition: AfterPackageDeactivationEvent.php:24
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\updateDatabase
‪updateDatabase()
Definition: InstallUtility.php:195
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Package\Exception\InvalidPackageStateException
Definition: InvalidPackageStateException.php:24
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:61
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Webhooks\Message\$siteIdentifier
‪identifier readonly int readonly array readonly string readonly string $siteIdentifier
Definition: PageModificationMessage.php:38
‪TYPO3\CMS\Core\Core\Bootstrap\loadExtTables
‪static loadExtTables(bool $allowCaching=true, FrontendInterface $coreCache=null)
Definition: Bootstrap.php:522
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\importStaticSqlFile
‪importStaticSqlFile(string $extensionKey, string $packagePath)
Definition: InstallUtility.php:317
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:1621
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory\createFromUserPreferences
‪createFromUserPreferences(?AbstractUserAuthentication $user)
Definition: LanguageServiceFactory.php:52
‪TYPO3\CMS\Extensionmanager\Domain\Model\Extension\returnInstallPaths
‪static array returnInstallPaths()
Definition: Extension.php:438
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\importSiteConfiguration
‪importSiteConfiguration(string $extensionKey, string $packagePath, Import $import=null)
Definition: InstallUtility.php:359
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\__construct
‪__construct(private readonly EventDispatcherInterface $eventDispatcher, private readonly FileHandlingUtility $fileHandlingUtility, private readonly ListUtility $listUtility, private readonly PackageManager $packageManager, private readonly CacheManager $cacheManager, private readonly Registry $registry, private readonly BootService $bootService, private readonly OpcodeCacheService $opcodeCacheService, private readonly SqlReader $sqlReader, private readonly SchemaMigrator $schemaMigrator, private readonly ExtensionConfiguration $extensionConfiguration, LanguageServiceFactory $languageServiceFactory,)
Definition: InstallUtility.php:62
‪TYPO3\CMS\Extensionmanager\Utility\InstallUtility\removeExtension
‪removeExtension(string $extension)
Definition: InstallUtility.php:219