‪TYPO3CMS  ‪main
ExtensionManagementUtility.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\EventDispatcher\EventDispatcherInterface;
21 use Symfony\Component\Finder\Finder;
30 use TYPO3\CMS\Core\Package\PackageManager;
32 
40 {
50  protected static bool ‪$extTablesWasReadFromCacheOnce = false;
51  protected static PackageManager ‪$packageManager;
52  protected static EventDispatcherInterface ‪$eventDispatcher;
53  protected static ?‪CacheManager ‪$cacheManager;
54 
61  public static function ‪setPackageManager(PackageManager ‪$packageManager): void
62  {
63  static::$packageManager = ‪$packageManager;
64  }
65 
71  public static function ‪setEventDispatcher(EventDispatcherInterface ‪$eventDispatcher): void
72  {
73  static::$eventDispatcher = ‪$eventDispatcher;
74  }
75 
79  protected static function ‪getCacheManager(): ‪CacheManager
80  {
81  return static::$cacheManager ??= GeneralUtility::makeInstance(CacheManager::class);
82  }
83 
84  /**************************************
85  *
86  * PATHS and other evaluation
87  *
88  ***************************************/
89 
93  public static function ‪isLoaded(string $key): bool
94  {
95  return static::$packageManager->isPackageActive($key);
96  }
97 
108  public static function ‪resolvePackagePath(string $path): string
109  {
110  return static::$packageManager->resolvePackagePath($path);
111  }
112 
120  public static function ‪extPath(string $key, string $script = ''): string
121  {
122  if (!static::$packageManager->isPackageActive($key)) {
123  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension key "' . $key . '" is NOT loaded!', 1365429656);
124  }
125  return static::$packageManager->getPackage($key)->getPackagePath() . $script;
126  }
127 
134  public static function ‪getCN(string $key): string
135  {
136  return str_starts_with($key, 'user_')
137  ? 'user_' . str_replace('_', '', substr($key, 5))
138  : 'tx_' . str_replace('_', '', $key);
139  }
140 
151  public static function ‪getExtensionVersion(string $key): string
152  {
153  if (empty($key)) {
154  throw new \InvalidArgumentException('Extension key must be a non-empty string.', 1294586096);
155  }
156  if (!static::isLoaded($key)) {
157  return '';
158  }
159  $version = static::$packageManager->getPackage($key)->getPackageMetaData()->getVersion();
160  if (empty($version)) {
161  throw new ‪PackageException('Version number in composer manifest of package "' . $key . '" is missing or invalid', 1395614959);
162  }
163  return $version;
164  }
165 
166  /**************************************
167  *
168  * Adding BACKEND features
169  * (related to core features)
170  *
171  ***************************************/
172 
183  public static function ‪addTCAcolumns(string $table, array $columnArray): void
184  {
185  if (is_array(‪$GLOBALS['TCA'][$table]['columns'] ?? false)) {
186  // Candidate for array_merge() if integer-keys will some day make trouble...
187  ‪$GLOBALS['TCA'][$table]['columns'] = array_merge(‪$GLOBALS['TCA'][$table]['columns'], $columnArray);
188  }
189  }
190 
204  public static function ‪addToAllTCAtypes(string $table, string $newFieldsString, string $typeList = '', string $position = ''): void
205  {
206  $newFieldsString = trim($newFieldsString);
207  if ($newFieldsString === '' || !is_array(‪$GLOBALS['TCA'][$table]['types'] ?? false)) {
208  return;
209  }
210  if ($position !== '') {
211  [$positionIdentifier, $entityName] = ‪GeneralUtility::trimExplode(':', $position, false, 2);
212  } else {
213  $positionIdentifier = '';
214  $entityName = '';
215  }
216  $palettesChanged = [];
217 
218  foreach (‪$GLOBALS['TCA'][$table]['types'] as $type => &$typeDetails) {
219  // skip if we don't want to add the field for this type
220  if ($typeList !== '' && !‪GeneralUtility::inList($typeList, $type)) {
221  continue;
222  }
223  // skip if fields were already added
224  if (!isset($typeDetails['showitem'])) {
225  continue;
226  }
227 
228  $fieldArray = ‪GeneralUtility::trimExplode(',', $typeDetails['showitem'], true);
229  if (in_array($newFieldsString, $fieldArray, true)) {
230  continue;
231  }
232 
233  $fieldExists = false;
234  $newPosition = '';
235  if (is_array(‪$GLOBALS['TCA'][$table]['palettes'] ?? false)) {
236  // Get the palette names used in current showitem
237  $paletteCount = preg_match_all('/(?:^|,) # Line start or a comma
238  (?:
239  \\s*\\-\\-palette\\-\\-;[^;]*;([^,$]*)| # --palette--;label;paletteName
240  \\s*\\b[^;,]+\\b(?:;[^;]*;([^;,]+))?[^,]* # field;label;paletteName
241  )/x', $typeDetails['showitem'], $paletteMatches);
242  if ($paletteCount > 0) {
243  $paletteNames = array_filter(array_merge($paletteMatches[1], $paletteMatches[2]));
244  if (!empty($paletteNames)) {
245  foreach ($paletteNames as $paletteName) {
246  if (!isset(‪$GLOBALS['TCA'][$table]['palettes'][$paletteName])) {
247  continue;
248  }
249  $palette = ‪$GLOBALS['TCA'][$table]['palettes'][$paletteName];
250  switch ($positionIdentifier) {
251  case 'after':
252  case 'before':
253  if (preg_match('/\\b' . preg_quote($entityName, '/') . '\\b/', $palette['showitem']) > 0 || $entityName === 'palette:' . $paletteName) {
254  $newPosition = $positionIdentifier . ':--palette--;;' . $paletteName;
255  }
256  break;
257  case 'replace':
258  // check if fields have been added to palette before
259  if (isset($palettesChanged[$paletteName])) {
260  $fieldExists = true;
261  continue 2;
262  }
263  if (preg_match('/\\b' . preg_quote($entityName, '/') . '\\b/', $palette['showitem']) > 0) {
264  ‪self::addFieldsToPalette($table, $paletteName, $newFieldsString, $position);
265  // Memorize that we already changed this palette, in case other types also use it
266  $palettesChanged[$paletteName] = true;
267  $fieldExists = true;
268  continue 2;
269  }
270  break;
271  default:
272  // Intentionally left blank
273  }
274  }
275  }
276  }
277  }
278  if ($fieldExists === false) {
279  $typeDetails['showitem'] = ‪self::executePositionedStringInsertion(
280  $typeDetails['showitem'],
281  $newFieldsString,
282  $newPosition !== '' ? $newPosition : $position
283  );
284  }
285  }
286  unset($typeDetails);
287  }
288 
332  public static function ‪addFieldsToAllPalettesOfField(string $table, string $field, string $addFields, string $insertionPosition = ''): void
333  {
334  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
335  return;
336  }
337  if (!is_array(‪$GLOBALS['TCA'][$table]['types'])) {
338  return;
339  }
340 
341  // Iterate through all types and search for the field that defines the palette to be extended
342  foreach (‪$GLOBALS['TCA'][$table]['types'] as $typeName => $typeArray) {
343  // Continue if types has no showitem at all or if requested field is not in it
344  if (!isset($typeArray['showitem']) || !str_contains($typeArray['showitem'], $field)) {
345  continue;
346  }
347  $fieldArrayWithOptions = ‪GeneralUtility::trimExplode(',', $typeArray['showitem']);
348  // Find the field we're handling
349  $newFieldStringArray = [];
350  foreach ($fieldArrayWithOptions as $fieldNumber => $fieldString) {
351  $newFieldStringArray[] = $fieldString;
352  $fieldArray = ‪GeneralUtility::trimExplode(';', $fieldString);
353  if ($fieldArray[0] !== $field) {
354  continue;
355  }
356  if (
357  isset($fieldArrayWithOptions[$fieldNumber + 1])
358  && str_starts_with($fieldArrayWithOptions[$fieldNumber + 1], '--palette--')
359  ) {
360  // Match for $field and next field is a palette - add fields to this one
361  $paletteName = ‪GeneralUtility::trimExplode(';', $fieldArrayWithOptions[$fieldNumber + 1]);
362  $paletteName = $paletteName[2];
363  ‪self::addFieldsToPalette($table, $paletteName, $addFields, $insertionPosition);
364  } else {
365  // Match for $field but next field is no palette - create a new one
366  $newPaletteName = 'generatedFor-' . $field;
367  ‪self::addFieldsToPalette($table, 'generatedFor-' . $field, $addFields, $insertionPosition);
368  $newFieldStringArray[] = '--palette--;;' . $newPaletteName;
369  }
370  }
371  ‪$GLOBALS['TCA'][$table]['types'][$typeName]['showitem'] = implode(', ', $newFieldStringArray);
372  }
373  }
374 
385  public static function ‪addFieldsToPalette(string $table, string $palette, string $addFields, string $insertionPosition = ''): void
386  {
387  if (isset(‪$GLOBALS['TCA'][$table])) {
388  $paletteData = &‪$GLOBALS['TCA'][$table]['palettes'][$palette];
389  // If palette already exists, merge the data:
390  if (is_array($paletteData)) {
391  $paletteData['showitem'] = ‪self::executePositionedStringInsertion($paletteData['showitem'], $addFields, $insertionPosition);
392  } else {
393  $paletteData['showitem'] = ‪self::removeDuplicatesForInsertion($addFields);
394  }
395  }
396  }
397 
429  public static function ‪addTcaSelectItem(string $table, string $field, array $item, string $relativeToField = '', string $relativePosition = ''): void
430  {
431  if ($relativePosition !== '' && $relativePosition !== 'before' && $relativePosition !== 'after' && $relativePosition !== 'replace') {
432  throw new \InvalidArgumentException('Relative position must be either empty or one of "before", "after", "replace".', 1303236967);
433  }
434  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
435  || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
436  ) {
437  throw new \RuntimeException('Given select field item list was not found.', 1303237468);
438  }
439  // Make sure item keys are integers
440  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] = array_values(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
441  if ($relativePosition !== '') {
442  // Insert at specified position
443  $matchedPosition = ‪ArrayUtility::filterByValueRecursive($relativeToField, ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
444  if (!empty($matchedPosition)) {
445  $relativeItemKey = key($matchedPosition);
446  if ($relativePosition === 'replace') {
447  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][$relativeItemKey] = $item;
448  } else {
449  if ($relativePosition === 'before') {
450  $offset = $relativeItemKey;
451  } else {
452  $offset = $relativeItemKey + 1;
453  }
454  array_splice(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'], $offset, 0, [0 => $item]);
455  }
456  } else {
457  // Insert at new item at the end of the array if relative position was not found
458  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
459  }
460  } else {
461  // Insert at new item at the end of the array
462  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
463  }
464  }
465 
476  public static function ‪addTcaSelectItemGroup(string $table, string $field, string $groupId, string $groupLabel, ?string $position = 'bottom'): void
477  {
478  if (!is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config'] ?? null)) {
479  throw new \RuntimeException('Given select field item list was not found.', 1586728563);
480  }
481  $itemGroups = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] ?? [];
482  // Group has been defined already, nothing to do
483  if (isset($itemGroups[$groupId])) {
484  return;
485  }
486  $position = (string)$position;
487  $positionGroupId = '';
488  if (str_contains($position, ':')) {
489  [$position, $positionGroupId] = explode(':', $position, 2);
490  }
491  // Referenced group was not not found, just append to the bottom
492  if (!isset($itemGroups[$positionGroupId])) {
493  $position = 'bottom';
494  }
495  switch ($position) {
496  case 'after':
497  $newItemGroups = [];
498  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
499  $newItemGroups[$existingGroupId] = $existingGroupLabel;
500  if ($positionGroupId === $existingGroupId) {
501  $newItemGroups[$groupId] = $groupLabel;
502  }
503  }
504  $itemGroups = $newItemGroups;
505  break;
506  case 'before':
507  $newItemGroups = [];
508  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
509  if ($positionGroupId === $existingGroupId) {
510  $newItemGroups[$groupId] = $groupLabel;
511  }
512  $newItemGroups[$existingGroupId] = $existingGroupLabel;
513  }
514  $itemGroups = $newItemGroups;
515  break;
516  case 'top':
517  $itemGroups = array_merge([$groupId => $groupLabel], $itemGroups);
518  break;
519  case 'bottom':
520  default:
521  $itemGroups[$groupId] = $groupLabel;
522  }
523  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] = $itemGroups;
524  }
525 
536  public static function ‪getFileFieldTCAConfig(string $fieldName, array $customSettingOverride = [], string $allowedFileExtensions = '', string $disallowedFileExtensions = ''): array
537  {
538  trigger_error(
539  'ExtensionManagementUtility::getFileFieldTCAConfig() will be removed in TYPO3 v13.0. Use TCA type "file" directly instead.',
540  E_USER_DEPRECATED
541  );
542 
543  $fileFieldTCAConfig = [
544  'type' => 'file',
545  'allowed' => $allowedFileExtensions,
546  'disallowed'=> $disallowedFileExtensions,
547  ];
548  ArrayUtility::mergeRecursiveWithOverrule($fileFieldTCAConfig, $customSettingOverride);
549  return $fileFieldTCAConfig;
550  }
551 
560  public static function ‪addFieldsToUserSettings(string $addFields, string $insertionPosition = ''): void
561  {
562  ‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'] = ‪self::executePositionedStringInsertion(‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'] ?? '', $addFields, $insertionPosition);
563  }
564 
582  protected static function ‪executePositionedStringInsertion(string $list, string $insertionList, string $insertionPosition = ''): string
583  {
584  $list = trim($list, ", \t\n\r\0\x0B");
585 
586  if ($insertionPosition !== '') {
587  [$location, $positionName] = ‪GeneralUtility::trimExplode(':', $insertionPosition, false, 2);
588  } else {
589  $location = '';
590  $positionName = '';
591  }
592 
593  if ($location !== 'replace') {
594  $insertionList = ‪self::removeDuplicatesForInsertion($insertionList, $list);
595  }
596 
597  if ($insertionList === '') {
598  return $list;
599  }
600  if ($list === '') {
601  return $insertionList;
602  }
603  if ($insertionPosition === '') {
604  return $list . ', ' . $insertionList;
605  }
606 
607  // The $insertPosition may be a palette: after:--palette--;;title
608  // In the $list the palette may contain a LLL string in between the ;;
609  // Adjust the regex to match that
610  $positionName = preg_quote($positionName, '/');
611  if (str_contains($positionName, ';;')) {
612  $positionName = str_replace(';;', ';[^;]*;', $positionName);
613  }
614 
615  $pattern = ('/(^|,\\s*)(' . $positionName . ')(;[^,$]+)?(,|$)/');
616  $newList = match ($location) {
617  'after' => preg_replace($pattern, '$1$2$3, ' . $insertionList . '$4', $list),
618  'before' => preg_replace($pattern, '$1' . $insertionList . ', $2$3$4', $list),
619  'replace' => preg_replace($pattern, '$1' . $insertionList . '$4', $list),
620  default => $list,
621  };
622 
623  // When preg_replace did not replace anything; append the $insertionList.
624  if ($newList === $list) {
625  return $list . ', ' . $insertionList;
626  }
627  return $newList;
628  }
629 
645  protected static function ‪removeDuplicatesForInsertion(string $insertionList, string $list = ''): string
646  {
647  $insertionListParts = preg_split('/\\s*,\\s*/', $insertionList);
648  $listMatches = [];
649  if ($list !== '') {
650  preg_match_all('/(?:^|,)\\s*\\b([^;,]+)\\b[^,]*/', $list, $listMatches);
651  $listMatches = $listMatches[1];
652  }
653 
654  $cleanInsertionListParts = [];
655  foreach ($insertionListParts as $fieldName) {
656  $fieldNameParts = explode(';', $fieldName, 2);
657  $cleanFieldName = $fieldNameParts[0];
658  if (
659  $cleanFieldName === '--linebreak--'
660  || (
661  !in_array($cleanFieldName, $cleanInsertionListParts, true)
662  && !in_array($cleanFieldName, $listMatches, true)
663  )
664  ) {
665  $cleanInsertionListParts[] = $fieldName;
666  }
667  }
668  return implode(', ', $cleanInsertionListParts);
669  }
670 
679  public static function ‪allowTableOnStandardPages(string $table): void
680  {
681  if ($table === '') {
682  return;
683  }
684  $registry = GeneralUtility::makeInstance(PageDoktypeRegistry::class);
685  $tables = explode(',', $table);
686  foreach ($tables as $singleTable) {
687  if (!$registry->isRecordTypeAllowedForDoktype($singleTable, null)) {
688  $registry->addAllowedRecordTypes(explode(',', $singleTable));
689  }
690  }
691  }
692 
703  public static function ‪addModule($main, $sub = '', $position = '', $path = null, $moduleConfiguration = [])
704  {
705  }
706 
720  public static function ‪insertModuleFunction($modname, $className, $_unused, $title, $MM_key = 'function', $WS = '')
721  {
722  // no-op: This is not in use anymore, use Modules.php instead
723  // This does not trigger a deprecation message as everything continues to work
724  }
725 
733  public static function ‪addPageTSConfig(string $content): void
734  {
735  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] .= chr(10) . $content;
736  }
737 
745  public static function ‪addUserTSConfig(string $content): void
746  {
747  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig'] .= chr(10) . $content;
748  }
749 
760  public static function ‪addLLrefForTCAdescr($key, $file)
761  {
762  }
763 
773  public static function ‪addNavigationComponent($module, $componentId, $extensionKey)
774  {
775  trigger_error('ExtensionManagementUtility::addNavigationComponent() will be removed in TYPO3 v13.0. Is not needed anymore. Remove any calls to this method.', E_USER_DEPRECATED);
776  }
777 
785  public static function ‪addCoreNavigationComponent($module, $componentId)
786  {
787  trigger_error('ExtensionManagementUtility::addCoreNavigationComponent() will be removed in TYPO3 v13.0. Is not needed anymore. Remove any calls to this method.', E_USER_DEPRECATED);
788  }
789 
790  /**************************************
791  *
792  * Adding SERVICES features
793  *
794  ***************************************/
803  public static function ‪addService(string $extKey, string $serviceType, string $serviceKey, array $info): void
804  {
805  if (!$serviceType) {
806  throw new \InvalidArgumentException('No serviceType given.', 1507321535);
807  }
808  $info['priority'] = max(0, min(100, $info['priority']));
809  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
810  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
811  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
812  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
813  // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
814  // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
815  // even the activation is possible (a unix service might be possible on windows for some reasons)
816  if (is_array(‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey] ?? false)) {
817  // No check is done here - there might be configuration values only the service type knows about, so
818  // we pass everything
819  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], ‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
820  }
821  // OS check
822  // Empty $os means 'not limited to one OS', therefore a check is not needed
823  if (!empty(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available']) && (‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] ?? '') != '') {
824  $os_type = ‪Environment::isWindows() ? 'WIN' : 'UNIX';
825  $os = ‪GeneralUtility::trimExplode(',', strtoupper(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
826  if (!in_array($os_type, $os, true)) {
827  ‪self::deactivateService($serviceType, $serviceKey);
828  }
829  }
830  // Convert subtype list to array for quicker access
831  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = [];
832  $serviceSubTypes = ‪GeneralUtility::trimExplode(',', $info['subtype']);
833  foreach ($serviceSubTypes as $subtype) {
834  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
835  }
836  }
837 
846  public static function ‪findService(string $serviceType, string $serviceSubType = '', array $excludeServiceKeys = []): array|false
847  {
848  $serviceKey = false;
849  $serviceInfo = false;
850  $priority = 0;
851  $quality = 0;
852  if (is_array(‪$GLOBALS['T3_SERVICES'][$serviceType])) {
853  foreach (‪$GLOBALS['T3_SERVICES'][$serviceType] as $key => $info) {
854  if (in_array($key, $excludeServiceKeys)) {
855  continue;
856  }
857  // Select a subtype randomly
858  // Useful to start a service by service key without knowing his subtypes - for testing purposes
859  if ($serviceSubType === '*') {
860  $serviceSubType = key($info['serviceSubTypes']);
861  }
862  // This matches empty subtype too
863  if (($info['available'] ?? false)
864  && (($info['subtype'] ?? null) == $serviceSubType || ($info['serviceSubTypes'][$serviceSubType] ?? false))
865  && ($info['priority'] ?? 0) >= $priority
866  ) {
867  // Has a lower quality than the already found, therefore we skip this service
868  if ($info['priority'] == $priority && $info['quality'] < $quality) {
869  continue;
870  }
871  // Check if the service is available
872  $info['available'] = ‪self::isServiceAvailable($serviceType, $key, $info);
873  // Still available after exec check?
874  if ($info['available']) {
875  $serviceKey = $key;
876  $priority = $info['priority'];
877  $quality = $info['quality'];
878  }
879  }
880  }
881  }
882  if ($serviceKey) {
883  $serviceInfo = ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey];
884  }
885  return $serviceInfo;
886  }
887 
896  public static function ‪findServiceByKey(string $serviceKey): array
897  {
898  if (is_array(‪$GLOBALS['T3_SERVICES'])) {
899  // Loop on all service types
900  // NOTE: we don't care about the actual type, we are looking for a specific key
901  foreach (‪$GLOBALS['T3_SERVICES'] as $serviceType => $servicesPerType) {
902  if (isset($servicesPerType[$serviceKey])) {
903  $serviceDetails = $servicesPerType[$serviceKey];
904  // Test if service is available
905  if (self::isServiceAvailable($serviceType, $serviceKey, $serviceDetails)) {
906  // We have found the right service, return its information
907  return $serviceDetails;
908  }
909  }
910  }
911  }
912  throw new \TYPO3\CMS\Core\Exception('Service not found for key: ' . $serviceKey, 1319217244);
913  }
914 
923  public static function ‪isServiceAvailable(string $serviceType, string $serviceKey, array $serviceDetails): bool
924  {
925  // If the service depends on external programs - check if they exists
926  if (trim($serviceDetails['exec'] ?? '')) {
927  $executables = ‪GeneralUtility::trimExplode(',', $serviceDetails['exec'], true);
928  foreach ($executables as $executable) {
929  // If at least one executable file is not available, exit early returning FALSE
930  if (!‪CommandUtility::checkCommand($executable)) {
931  ‪self::deactivateService($serviceType, $serviceKey);
932  return false;
933  }
934  }
935  }
936  // The service is available
937  return true;
938  }
939 
946  public static function ‪deactivateService(string $serviceType, string $serviceKey): void
947  {
948  // ... maybe it's better to move non-available services to a different array??
949  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] = false;
950  }
951 
952  /**************************************
953  *
954  * Adding FRONTEND features
955  *
956  ***************************************/
970  public static function ‪addPlugin(array $itemArray, string $type = 'list_type', ?string $extensionKey = null): void
971  {
972  // $extensionKey is required, but presumably for BC reasons it still lives after $type in the
973  // parameter list, and $type is nominally optional.
974  if (!isset($extensionKey)) {
975  throw new \InvalidArgumentException(
976  'No extension key could be determined when calling addPlugin()!'
977  . LF
978  . 'This method is meant to be called from Configuration/TCA/Overrides files. '
979  . 'The extension key needs to be specified as third parameter. '
980  . 'Calling it from any other place e.g. ext_localconf.php does not work and is not supported.',
981  1404068038
982  );
983  }
984  if (!isset($itemArray[2]) || !$itemArray[2]) {
985  // @todo do we really set $itemArray[2], even if we cannot find an icon? (as that means it's set to 'EXT:foobar/')
986  $itemArray[2] = 'EXT:' . $extensionKey . '/' . static::getExtensionIcon(static::$packageManager->getPackage($extensionKey)->getPackagePath());
987  } elseif ($type === 'CType' && !isset(‪$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$itemArray[1]])) {
988  // Set the type icon as well
989  ‪$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$itemArray[1]] = $itemArray[2];
990  }
991  if (!isset($itemArray[3])) {
992  $itemArray[3] = 'default';
993  }
994  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'])) {
995  foreach (‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'] as $k => $v) {
996  if ((string)($v['value'] ?? '') === (string)$itemArray[1]) {
997  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][$k] = [
998  'label' => $itemArray[0] ?? '',
999  'value' => $itemArray[1] ?? '',
1000  'icon' => $itemArray[2],
1001  'group' => $itemArray[3],
1002  ];
1003  return;
1004  }
1005  }
1006  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][] = [
1007  'label' => $itemArray[0] ?? '',
1008  'value' => $itemArray[1] ?? '',
1009  'icon' => $itemArray[2],
1010  'group' => $itemArray[3],
1011  ];
1012  }
1013  // Ensure to have at least some basic information available when editing the new type in FormEngine
1014  if ($type === 'CType' && !isset(‪$GLOBALS['TCA']['tt_content']['types'][$itemArray[1]]) && isset(‪$GLOBALS['TCA']['tt_content']['types']['header'])) {
1015  ‪$GLOBALS['TCA']['tt_content']['types'][$itemArray[1]] = ‪$GLOBALS['TCA']['tt_content']['types']['header'];
1016  }
1017  }
1018 
1029  public static function ‪addPiFlexFormValue(string $piKeyToMatch, string $value, string $CTypeToMatch = 'list'): void
1030  {
1031  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'])) {
1032  ‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'][$piKeyToMatch . ',' . $CTypeToMatch] = $value;
1033  }
1034  }
1035 
1045  public static function ‪addToInsertRecords(string $table, string $content_table = 'tt_content', string $content_field = 'records'): void
1046  {
1047  if (is_array(‪$GLOBALS['TCA'][$content_table]['columns']) && isset(‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'])) {
1048  ‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'] .= ',' . $table;
1049  }
1050  }
1051 
1076  public static function ‪addPItoST43(string $key, string $_ = '', string $suffix = '', string $type = 'list_type', bool $cacheable = false): void
1077  {
1078  $cN = ‪self::getCN($key);
1079  // General plugin
1080  $pluginContent = trim('
1081 plugin.' . $cN . $suffix . ' = USER' . ($cacheable ? '' : '_INT') . '
1082 plugin.' . $cN . $suffix . '.userFunc = ' . $cN . $suffix . '->main
1083 ');
1084  ‪self::addTypoScript($key, 'setup', '
1085 # Setting ' . $key . ' plugin TypoScript
1086 ' . $pluginContent);
1087  // Add after defaultContentRendering
1088  switch ($type) {
1089  case 'list_type':
1090  $addLine = 'tt_content.list.20.' . $key . $suffix . ' = < plugin.' . $cN . $suffix;
1091  break;
1092  case 'CType':
1093  $addLine = trim('
1094 tt_content.' . $key . $suffix . ' =< lib.contentElement
1095 tt_content.' . $key . $suffix . ' {
1096  templateName = Generic
1097  20 =< plugin.' . $cN . $suffix . '
1098 }
1099 ');
1100  break;
1101  case 'includeLib':
1102  $addLine = 'page.1000 = < plugin.' . $cN . $suffix;
1103  break;
1104  default:
1105  $addLine = '';
1106  }
1107  if ($addLine) {
1108  ‪self::addTypoScript($key, 'setup', '
1109 # Setting ' . $key . ' plugin TypoScript
1110 ' . $addLine . '
1111 ', 'defaultContentRendering');
1112  }
1113  }
1114 
1130  public static function ‪addStaticFile(string $extKey, string $path, string $title): void
1131  {
1132  if (!$extKey) {
1133  throw new \InvalidArgumentException('No extension key given.', 1507321291);
1134  }
1135  if (!$path) {
1136  throw new \InvalidArgumentException('No file path given.', 1507321297);
1137  }
1138  if (is_array(‪$GLOBALS['TCA']['sys_template']['columns'])) {
1139  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $path);
1140  $itemArray = ['label' => trim($title . ' (' . $extKey . ')'), 'value' => $value];
1141  ‪$GLOBALS['TCA']['sys_template']['columns']['include_static_file']['config']['items'][] = $itemArray;
1142  }
1143  }
1144 
1154  public static function ‪registerPageTSConfigFile(string $extKey, string $filePath, string $title): void
1155  {
1156  if (!$extKey) {
1157  throw new \InvalidArgumentException('No extension key given.', 1447789490);
1158  }
1159  if (!$filePath) {
1160  throw new \InvalidArgumentException('No file path given.', 1447789491);
1161  }
1162  if (!is_array(‪$GLOBALS['TCA']['pages']['columns'] ?? null)) {
1163  throw new \InvalidArgumentException('No TCA definition for table "pages".', 1447789492);
1164  }
1165 
1166  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $filePath);
1167  $itemArray = ['label' => trim($title . ' (' . $extKey . ')'), 'value' => $value];
1168  ‪$GLOBALS['TCA']['pages']['columns']['tsconfig_includes']['config']['items'][] = $itemArray;
1169  }
1170 
1178  public static function ‪addTypoScriptSetup(string $content): void
1179  {
1180  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'] ??= '';
1181  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'])) {
1182  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'] .= LF;
1183  }
1184  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'] .= $content;
1185  }
1186 
1194  public static function ‪addTypoScriptConstants(string $content): void
1195  {
1196  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'] ??= '';
1197  if (!empty(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'])) {
1198  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'] .= LF;
1199  }
1200  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'] .= $content;
1201  }
1202 
1220  public static function ‪addTypoScript(string $key, string $type, string $content, int|string $afterStaticUid = 0): void
1221  {
1222  if ($type !== 'setup' && $type !== 'constants') {
1223  throw new \InvalidArgumentException('Argument $type must be set to either "setup" or "constants" when calling addTypoScript from extension "' . $key . '"', 1507321200);
1224  }
1225  $content = '
1226 
1227 [GLOBAL]
1228 #############################################
1229 ## TypoScript added by extension "' . $key . '"
1230 #############################################
1231 
1232 ' . $content;
1233  if ($afterStaticUid) {
1234  // If 'defaultContentRendering' is targeted (formerly static uid 43),
1235  // the content is added after TypoScript of type contentRendering, e.g. fluid_styled_content, see
1236  // EXT:core/Classes/TypoScript/IncludeTree/SysTemplateTreeBuilder.php for more information on how the code is parsed.
1237  if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
1238  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] ??= '';
1239  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
1240  } else {
1241  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] ??= '';
1242  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
1243  }
1244  } else {
1245  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] ??= '';
1246  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
1247  }
1248  }
1249 
1250  /***************************************
1251  *
1252  * Internal extension management methods
1253  *
1254  ***************************************/
1261  public static function ‪getExtensionIcon(string $extensionPath, bool $returnFullPath = false): string
1262  {
1263  $icon = '';
1264  $locationsToCheckFor = [
1265  'Resources/Public/Icons/Extension.svg',
1266  'Resources/Public/Icons/Extension.png',
1267  'Resources/Public/Icons/Extension.gif',
1268  'ext_icon.svg',
1269  'ext_icon.png',
1270  'ext_icon.gif',
1271  ];
1272  foreach ($locationsToCheckFor as $fileLocation) {
1273  if (file_exists($extensionPath . $fileLocation)) {
1274  $icon = $fileLocation;
1275  break;
1276  }
1277  }
1278  return $returnFullPath ? $extensionPath . $icon : $icon;
1279  }
1280 
1293  public static function ‪loadExtLocalconf(bool $allowCaching = true, ‪FrontendInterface $codeCache = null): void
1294  {
1295  if ($allowCaching) {
1296  $codeCache = $codeCache ?? ‪self::getCacheManager()->getCache('core');
1297  $cacheIdentifier = ‪self::getExtLocalconfCacheIdentifier();
1298  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1299  if (!$hasCache) {
1302  }
1303  } else {
1305  }
1306  }
1307 
1311  protected static function ‪loadSingleExtLocalconfFiles(): void
1312  {
1313  foreach (static::$packageManager->getActivePackages() as $package) {
1314  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1315  if (file_exists($extLocalconfPath)) {
1316  require $extLocalconfPath;
1317  }
1318  }
1319  }
1320 
1326  public static function ‪createExtLocalconfCacheEntry(‪FrontendInterface $codeCache): void
1327  {
1328  $phpCodeToCache = [];
1329  // Set same globals as in loadSingleExtLocalconfFiles()
1330  $phpCodeToCache[] = '';
1333  $phpCodeToCache[] = '';
1334  // Iterate through loaded extensions and add ext_localconf content
1335  foreach (static::$packageManager->getActivePackages() as $package) {
1336  $extensionKey = $package->getPackageKey();
1337  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1338  if (@file_exists($extLocalconfPath)) {
1339  // Include a header per extension to make the cache file more readable
1340  $phpCodeToCache[] = '';
1344  $phpCodeToCache[] = '';
1345  // Add ext_localconf.php content of extension
1346  $phpCodeToCache[] = 'namespace {';
1347  $phpCodeToCache[] = trim((string)file_get_contents($extLocalconfPath));
1348  $phpCodeToCache[] = '}';
1349  $phpCodeToCache[] = '';
1350  $phpCodeToCache[] = '';
1351  }
1352  }
1353  $phpCodeToCache = implode(LF, $phpCodeToCache);
1354  // Remove all start and ending php tags from content
1355  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1356  $phpCodeToCache = preg_replace('/declare\\s?+\\(\\s?+strict_types\\s?+=\\s?+1\\s?+\\);/is', '', (string)$phpCodeToCache);
1357  $codeCache->‪set(self::getExtLocalconfCacheIdentifier(), $phpCodeToCache);
1358  }
1359 
1363  protected static function ‪getExtLocalconfCacheIdentifier(): string
1364  {
1365  return (new ‪PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('ext_localconf')->toString();
1366  }
1367 
1381  public static function ‪loadBaseTca(bool $allowCaching = true, ‪FrontendInterface $codeCache = null): void
1382  {
1383  if ($allowCaching) {
1384  $codeCache = $codeCache ?? ‪self::getCacheManager()->getCache('core');
1385  $cacheIdentifier = static::getBaseTcaCacheIdentifier();
1386  $cacheData = $codeCache->require($cacheIdentifier);
1387  if ($cacheData) {
1388  ‪$GLOBALS['TCA'] = $cacheData['tca'];
1389  } else {
1390  static::buildBaseTcaFromSingleFiles();
1391  static::createBaseTcaCacheFile($codeCache);
1392  }
1393  } else {
1394  static::buildBaseTcaFromSingleFiles();
1395  }
1396 
1397  $allowedRecordTypesForDefault = [];
1398  foreach (‪$GLOBALS['TCA'] as $table => $tableConfiguration) {
1399  if ($tableConfiguration['ctrl']['security']['ignorePageTypeRestriction'] ?? false) {
1400  $allowedRecordTypesForDefault[] = $table;
1401  }
1402  }
1403  GeneralUtility::makeInstance(PageDoktypeRegistry::class)->addAllowedRecordTypes($allowedRecordTypesForDefault);
1404  }
1405 
1414  public static function ‪buildBaseTcaFromSingleFiles(): void
1415  {
1416  ‪$GLOBALS['TCA'] = [];
1417 
1418  $activePackages = static::$packageManager->getActivePackages();
1419 
1420  // To require TCA in a safe scoped environment avoiding local variable clashes.
1421  // @see TYPO3\CMS\Core\Tests\Functional\Utility\ExtensionManagementUtility\ExtensionManagementUtilityTcaRequireTest
1422  // Note: Return type 'mixed' is intended, otherwise broken TCA files with missing "return [];" statement would
1423  // emit a "return value must be of type array, int returned" PHP TypeError. This is mitigated by an array
1424  // check below.
1425  $scopedReturnRequire = static function (string $filename): mixed {
1426  return require $filename;
1427  };
1428  // First load "full table" files from Configuration/TCA
1429  foreach ($activePackages as $package) {
1430  try {
1431  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA');
1432  } catch (\InvalidArgumentException $e) {
1433  // No such directory in this package
1434  continue;
1435  }
1436  foreach (‪$finder as $fileInfo) {
1437  $tcaOfTable = $scopedReturnRequire($fileInfo->getPathname());
1438  if (is_array($tcaOfTable)) {
1439  $tcaTableName = substr($fileInfo->getBasename(), 0, -4);
1440  ‪$GLOBALS['TCA'][$tcaTableName] = $tcaOfTable;
1441  }
1442  }
1443  }
1444 
1445  // To require TCA Overrides in a safe scoped environment avoiding local variable clashes.
1446  // @see TYPO3\CMS\Core\Tests\Functional\Utility\ExtensionManagementUtility\ExtensionManagementUtilityTcaOverrideRequireTest
1447  $scopedRequire = static function (string $filename): void {
1448  require $filename;
1449  };
1450  // Execute override files from Configuration/TCA/Overrides
1451  foreach ($activePackages as $package) {
1452  try {
1453  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA/Overrides');
1454  } catch (\InvalidArgumentException $e) {
1455  // No such directory in this package
1456  continue;
1457  }
1458  foreach (‪$finder as $fileInfo) {
1459  $scopedRequire($fileInfo->getPathname());
1460  }
1461  }
1462 
1463  // Call the TcaMigration and log any deprecations.
1464  $tcaMigration = GeneralUtility::makeInstance(TcaMigration::class);
1465  ‪$GLOBALS['TCA'] = $tcaMigration->migrate(‪$GLOBALS['TCA']);
1466  $messages = $tcaMigration->getMessages();
1467  if (!empty($messages)) {
1468  $context = 'Automatic TCA migration done during bootstrap. Please adapt TCA accordingly, these migrations'
1469  . ' will be removed. The backend module "Configuration -> TCA" shows the modified values.'
1470  . ' Please adapt these areas:';
1471  array_unshift($messages, $context);
1472  trigger_error(implode(LF, $messages), E_USER_DEPRECATED);
1473  }
1474 
1475  // TCA preparation
1476  $tcaPreparation = GeneralUtility::makeInstance(TcaPreparation::class);
1477  ‪$GLOBALS['TCA'] = $tcaPreparation->prepare(‪$GLOBALS['TCA']);
1478 
1479  static::dispatchTcaIsBeingBuiltEvent(‪$GLOBALS['TCA']);
1480  }
1481 
1485  protected static function ‪dispatchTcaIsBeingBuiltEvent(array ‪$tca): void
1486  {
1487  ‪$GLOBALS['TCA'] = static::$eventDispatcher->dispatch(new ‪AfterTcaCompilationEvent(‪$tca))->getTca();
1488  }
1489 
1496  public static function ‪createBaseTcaCacheFile(‪FrontendInterface $codeCache): void
1497  {
1498  $codeCache->‪set(
1499  static::getBaseTcaCacheIdentifier(),
1500  'return '
1501  . var_export(['tca' => ‪$GLOBALS['TCA']], true)
1502  . ';'
1503  );
1504  }
1505 
1509  protected static function ‪getBaseTcaCacheIdentifier(): string
1510  {
1511  return (new ‪PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('tca_base')->toString();
1512  }
1513 
1525  public static function ‪loadExtTables(bool $allowCaching = true, ‪FrontendInterface $codeCache = null): void
1526  {
1527  if ($allowCaching && !self::$extTablesWasReadFromCacheOnce) {
1528  self::$extTablesWasReadFromCacheOnce = true;
1529  $cacheIdentifier = ‪self::getExtTablesCacheIdentifier();
1530  $codeCache = $codeCache ?? ‪self::getCacheManager()->getCache('core');
1531  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1532  if (!$hasCache) {
1535  }
1536  } else {
1538  }
1539  }
1540 
1544  protected static function ‪loadSingleExtTablesFiles(): void
1545  {
1546  // Load each ext_tables.php file of loaded extensions
1547  foreach (static::$packageManager->getActivePackages() as $package) {
1548  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1549  if (@file_exists($extTablesPath)) {
1550  require $extTablesPath;
1551  }
1552  }
1553  }
1554 
1560  public static function ‪createExtTablesCacheEntry(‪FrontendInterface $codeCache): void
1561  {
1562  $phpCodeToCache = [];
1563  // Set same globals as in loadSingleExtTablesFiles()
1564  $phpCodeToCache[] = '';
1567  $phpCodeToCache[] = '';
1568  // Iterate through loaded extensions and add ext_tables content
1569  foreach (static::$packageManager->getActivePackages() as $package) {
1570  $extensionKey = $package->getPackageKey();
1571  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1572  if (@file_exists($extTablesPath)) {
1573  // Include a header per extension to make the cache file more readable
1574  $phpCodeToCache[] = '';
1578  $phpCodeToCache[] = '';
1579  // Add ext_tables.php content of extension
1580  $phpCodeToCache[] = 'namespace {';
1581  $phpCodeToCache[] = trim((string)file_get_contents($extTablesPath));
1582  $phpCodeToCache[] = '}';
1583  $phpCodeToCache[] = '';
1584  }
1585  }
1586  $phpCodeToCache = implode(LF, $phpCodeToCache);
1587  // Remove all start and ending php tags from content
1588  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1589  $phpCodeToCache = preg_replace('/declare\\s?+\\(\\s?+strict_types\\s?+=\\s?+1\\s?+\\);/is', '', (string)$phpCodeToCache);
1590  $codeCache->‪set(self::getExtTablesCacheIdentifier(), $phpCodeToCache);
1591  }
1592 
1596  protected static function ‪getExtTablesCacheIdentifier(): string
1597  {
1598  return (new ‪PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('ext_tables')->toString();
1599  }
1600 
1604  public static function ‪getLoadedExtensionListArray(): array
1605  {
1606  return array_keys(static::$packageManager->getActivePackages());
1607  }
1608 
1615  public static function ‪loadExtension(string $extensionKey): void
1616  {
1617  if (static::$packageManager->isPackageActive($extensionKey)) {
1618  throw new \RuntimeException('Extension already loaded', 1342345486);
1619  }
1620  static::$packageManager->activatePackage($extensionKey);
1621  }
1622 
1628  public static function ‪unloadExtension(string $extensionKey): void
1629  {
1630  if (!static::$packageManager->isPackageActive($extensionKey)) {
1631  throw new \RuntimeException('Extension not loaded', 1342345487);
1632  }
1633  static::$packageManager->deactivatePackage($extensionKey);
1634  }
1635 }
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addService
‪static addService(string $extKey, string $serviceType, string $serviceKey, array $info)
Definition: ExtensionManagementUtility.php:803
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPiFlexFormValue
‪static addPiFlexFormValue(string $piKeyToMatch, string $value, string $CTypeToMatch='list')
Definition: ExtensionManagementUtility.php:1029
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\dispatchTcaIsBeingBuiltEvent
‪static dispatchTcaIsBeingBuiltEvent(array $tca)
Definition: ExtensionManagementUtility.php:1485
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:916
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addModule
‪static addModule($main, $sub='', $position='', $path=null, $moduleConfiguration=[])
Definition: ExtensionManagementUtility.php:703
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToInsertRecords
‪static addToInsertRecords(string $table, string $content_table='tt_content', string $content_field='records')
Definition: ExtensionManagementUtility.php:1045
‪TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry
Definition: PageDoktypeRegistry.php:36
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getLoadedExtensionListArray
‪static getLoadedExtensionListArray()
Definition: ExtensionManagementUtility.php:1604
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findServiceByKey
‪static array findServiceByKey(string $serviceKey)
Definition: ExtensionManagementUtility.php:896
‪TYPO3\CMS\Core\Migrations\TcaMigration
Definition: TcaMigration.php:31
‪$finder
‪if(PHP_SAPI !=='cli') $finder
Definition: header-comment.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtensionIcon
‪static getExtensionIcon(string $extensionPath, bool $returnFullPath=false)
Definition: ExtensionManagementUtility.php:1261
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtensionVersion
‪static string getExtensionVersion(string $key)
Definition: ExtensionManagementUtility.php:151
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToAllTCAtypes
‪static addToAllTCAtypes(string $table, string $newFieldsString, string $typeList='', string $position='')
Definition: ExtensionManagementUtility.php:204
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getFileFieldTCAConfig
‪static getFileFieldTCAConfig(string $fieldName, array $customSettingOverride=[], string $allowedFileExtensions='', string $disallowedFileExtensions='')
Definition: ExtensionManagementUtility.php:536
‪TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent
Definition: AfterTcaCompilationEvent.php:27
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtTables
‪static loadExtTables(bool $allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1525
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isServiceAvailable
‪static bool isServiceAvailable(string $serviceType, string $serviceKey, array $serviceDetails)
Definition: ExtensionManagementUtility.php:923
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtLocalconfCacheEntry
‪static createExtLocalconfCacheEntry(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1326
‪TYPO3\CMS\Core\Package\Cache\PackageDependentCacheIdentifier
Definition: PackageDependentCacheIdentifier.php:30
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptSetup
‪static addTypoScriptSetup(string $content)
Definition: ExtensionManagementUtility.php:1178
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$eventDispatcher
‪static EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementUtility.php:52
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtLocalconfFiles
‪static loadSingleExtLocalconfFiles()
Definition: ExtensionManagementUtility.php:1311
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPlugin
‪static addPlugin(array $itemArray, string $type='list_type', ?string $extensionKey=null)
Definition: ExtensionManagementUtility.php:970
‪TYPO3\CMS\Core\Utility
Definition: ArrayUtility.php:18
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtLocalconf
‪static loadExtLocalconf(bool $allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1293
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtTablesCacheEntry
‪static createExtTablesCacheEntry(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1560
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\deactivateService
‪static deactivateService(string $serviceType, string $serviceKey)
Definition: ExtensionManagementUtility.php:946
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addStaticFile
‪static addStaticFile(string $extKey, string $path, string $title)
Definition: ExtensionManagementUtility.php:1130
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItemGroup
‪static addTcaSelectItemGroup(string $table, string $field, string $groupId, string $groupLabel, ?string $position='bottom')
Definition: ExtensionManagementUtility.php:476
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPItoST43
‪static addPItoST43(string $key, string $_='', string $suffix='', string $type='list_type', bool $cacheable=false)
Definition: ExtensionManagementUtility.php:1076
‪TYPO3\CMS\Core\Utility\CommandUtility\checkCommand
‪static bool int checkCommand(string $cmd, string $handler='')
Definition: CommandUtility.php:164
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static isLoaded(string $key)
Definition: ExtensionManagementUtility.php:93
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:40
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTCAcolumns
‪static addTCAcolumns(string $table, array $columnArray)
Definition: ExtensionManagementUtility.php:183
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtLocalconfCacheIdentifier
‪static getExtLocalconfCacheIdentifier()
Definition: ExtensionManagementUtility.php:1363
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\removeDuplicatesForInsertion
‪static string removeDuplicatesForInsertion(string $insertionList, string $list='')
Definition: ExtensionManagementUtility.php:645
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToAllPalettesOfField
‪static addFieldsToAllPalettesOfField(string $table, string $field, string $addFields, string $insertionPosition='')
Definition: ExtensionManagementUtility.php:332
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToPalette
‪static addFieldsToPalette(string $table, string $palette, string $addFields, string $insertionPosition='')
Definition: ExtensionManagementUtility.php:385
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtension
‪static loadExtension(string $extensionKey)
Definition: ExtensionManagementUtility.php:1615
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static extPath(string $key, string $script='')
Definition: ExtensionManagementUtility.php:120
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$extTablesWasReadFromCacheOnce
‪static bool $extTablesWasReadFromCacheOnce
Definition: ExtensionManagementUtility.php:50
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setPackageManager
‪static setPackageManager(PackageManager $packageManager)
Definition: ExtensionManagementUtility.php:61
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findService
‪static array false findService(string $serviceType, string $serviceSubType='', array $excludeServiceKeys=[])
Definition: ExtensionManagementUtility.php:846
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadBaseTca
‪static loadBaseTca(bool $allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1381
‪TYPO3\CMS\Core\Preparations\TcaPreparation
Definition: TcaPreparation.php:28
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addLLrefForTCAdescr
‪static addLLrefForTCAdescr($key, $file)
Definition: ExtensionManagementUtility.php:760
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getBaseTcaCacheIdentifier
‪static getBaseTcaCacheIdentifier()
Definition: ExtensionManagementUtility.php:1509
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtTablesFiles
‪static loadSingleExtTablesFiles()
Definition: ExtensionManagementUtility.php:1544
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptConstants
‪static addTypoScriptConstants(string $content)
Definition: ExtensionManagementUtility.php:1194
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:36
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\insertModuleFunction
‪static insertModuleFunction($modname, $className, $_unused, $title, $MM_key='function', $WS='')
Definition: ExtensionManagementUtility.php:720
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\allowTableOnStandardPages
‪static allowTableOnStandardPages(string $table)
Definition: ExtensionManagementUtility.php:679
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addUserTSConfig
‪static addUserTSConfig(string $content)
Definition: ExtensionManagementUtility.php:745
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$packageManager
‪static PackageManager $packageManager
Definition: ExtensionManagementUtility.php:51
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtTablesCacheIdentifier
‪static getExtTablesCacheIdentifier()
Definition: ExtensionManagementUtility.php:1596
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCacheManager
‪static getCacheManager()
Definition: ExtensionManagementUtility.php:79
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\registerPageTSConfigFile
‪static registerPageTSConfigFile(string $extKey, string $filePath, string $title)
Definition: ExtensionManagementUtility.php:1154
‪TYPO3\CMS\Core\Utility\ArrayUtility\filterByValueRecursive
‪static array filterByValueRecursive(mixed $needle='', array $haystack=[])
Definition: ArrayUtility.php:101
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToUserSettings
‪static addFieldsToUserSettings(string $addFields, string $insertionPosition='')
Definition: ExtensionManagementUtility.php:560
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItem
‪static addTcaSelectItem(string $table, string $field, array $item, string $relativeToField='', string $relativePosition='')
Definition: ExtensionManagementUtility.php:429
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\unloadExtension
‪static unloadExtension(string $extensionKey)
Definition: ExtensionManagementUtility.php:1628
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createBaseTcaCacheFile
‪static createBaseTcaCacheFile(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1496
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:532
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\resolvePackagePath
‪static resolvePackagePath(string $path)
Definition: ExtensionManagementUtility.php:108
‪TYPO3\CMS\Core\Package\Exception
Definition: InvalidPackageKeyException.php:16
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setEventDispatcher
‪static setEventDispatcher(EventDispatcherInterface $eventDispatcher)
Definition: ExtensionManagementUtility.php:71
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\executePositionedStringInsertion
‪static string executePositionedStringInsertion(string $list, string $insertionList, string $insertionPosition='')
Definition: ExtensionManagementUtility.php:582
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface\set
‪set($entryIdentifier, $data, array $tags=[], $lifetime=null)
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addNavigationComponent
‪static addNavigationComponent($module, $componentId, $extensionKey)
Definition: ExtensionManagementUtility.php:773
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPageTSConfig
‪static addPageTSConfig(string $content)
Definition: ExtensionManagementUtility.php:733
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\buildBaseTcaFromSingleFiles
‪static buildBaseTcaFromSingleFiles()
Definition: ExtensionManagementUtility.php:1414
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$cacheManager
‪static CacheManager $cacheManager
Definition: ExtensionManagementUtility.php:53
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScript
‪static addTypoScript(string $key, string $type, string $content, int|string $afterStaticUid=0)
Definition: ExtensionManagementUtility.php:1220
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addCoreNavigationComponent
‪static addCoreNavigationComponent($module, $componentId)
Definition: ExtensionManagementUtility.php:785
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCN
‪static getCN(string $key)
Definition: ExtensionManagementUtility.php:134
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static isWindows()
Definition: Environment.php:287