‪TYPO3CMS  11.5
ExtensionManagementUtility.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 Symfony\Component\Finder\Finder;
32 use TYPO3\CMS\Core\Package\PackageManager;
35 
43 {
54  protected static ‪$extTablesWasReadFromCacheOnce = false;
55 
59  protected static ‪$packageManager;
60 
68  public static function ‪setPackageManager(PackageManager ‪$packageManager)
69  {
70  static::$packageManager = ‪$packageManager;
71  }
72 
76  protected static ‪$eventDispatcher;
77 
84  public static function ‪setEventDispatcher(EventDispatcherInterface ‪$eventDispatcher)
85  {
86  static::$eventDispatcher = ‪$eventDispatcher;
87  }
88 
92  protected static ‪$cacheManager;
93 
99  protected static function ‪getCacheManager()
100  {
101  if (static::$cacheManager === null) {
102  static::$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
103  }
104  return static::$cacheManager;
105  }
106 
107  /**************************************
108  *
109  * PATHS and other evaluation
110  *
111  ***************************************/
118  public static function ‪isLoaded($key)
119  {
120  return static::$packageManager->isPackageActive($key);
121  }
122 
133  public static function ‪resolvePackagePath(string $path): string
134  {
135  return static::$packageManager->resolvePackagePath($path);
136  }
137 
146  public static function ‪extPath($key, $script = '')
147  {
148  if (!static::$packageManager->isPackageActive($key)) {
149  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension key "' . $key . '" is NOT loaded!', 1365429656);
150  }
151  return static::$packageManager->getPackage($key)->getPackagePath() . $script;
152  }
153 
161  public static function ‪getCN($key)
162  {
163  return strpos($key, 'user_') === 0 ? 'user_' . str_replace('_', '', substr($key, 5)) : 'tx_' . str_replace('_', '', $key);
164  }
165 
176  public static function ‪getExtensionVersion($key)
177  {
178  if (!is_string($key) || empty($key)) {
179  throw new \InvalidArgumentException('Extension key must be a non-empty string.', 1294586096);
180  }
181  if (!static::isLoaded($key)) {
182  return '';
183  }
184  $version = static::$packageManager->getPackage($key)->getPackageMetaData()->getVersion();
185  if (empty($version)) {
186  throw new ‪PackageException('Version number in composer manifest of package "' . $key . '" is missing or invalid', 1395614959);
187  }
188  return $version;
189  }
190 
191  /**************************************
192  *
193  * Adding BACKEND features
194  * (related to core features)
195  *
196  ***************************************/
207  public static function ‪addTCAcolumns($table, $columnArray)
208  {
209  if (is_array($columnArray) && is_array(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
210  // Candidate for array_merge() if integer-keys will some day make trouble...
211  ‪$GLOBALS['TCA'][$table]['columns'] = array_merge(‪$GLOBALS['TCA'][$table]['columns'], $columnArray);
212  }
213  }
214 
228  public static function ‪addToAllTCAtypes($table, $newFieldsString, $typeList = '', $position = '')
229  {
230  $newFieldsString = trim($newFieldsString);
231  if ($newFieldsString === '' || !is_array(‪$GLOBALS['TCA'][$table]['types'] ?? false)) {
232  return;
233  }
234  if ($position !== '') {
235  [$positionIdentifier, $entityName] = ‪GeneralUtility::trimExplode(':', $position, false, 2);
236  } else {
237  $positionIdentifier = '';
238  $entityName = '';
239  }
240  $palettesChanged = [];
241 
242  foreach (‪$GLOBALS['TCA'][$table]['types'] as $type => &$typeDetails) {
243  // skip if we don't want to add the field for this type
244  if ($typeList !== '' && !GeneralUtility::inList($typeList, $type)) {
245  continue;
246  }
247  // skip if fields were already added
248  if (!isset($typeDetails['showitem'])) {
249  continue;
250  }
251 
252  $fieldArray = ‪GeneralUtility::trimExplode(',', $typeDetails['showitem'], true);
253  if (in_array($newFieldsString, $fieldArray, true)) {
254  continue;
255  }
256 
257  $fieldExists = false;
258  $newPosition = '';
259  if (is_array(‪$GLOBALS['TCA'][$table]['palettes'] ?? false)) {
260  // Get the palette names used in current showitem
261  $paletteCount = preg_match_all('/(?:^|,) # Line start or a comma
262  (?:
263  \\s*\\-\\-palette\\-\\-;[^;]*;([^,$]*)| # --palette--;label;paletteName
264  \\s*\\b[^;,]+\\b(?:;[^;]*;([^;,]+))?[^,]* # field;label;paletteName
265  )/x', $typeDetails['showitem'], $paletteMatches);
266  if ($paletteCount > 0) {
267  $paletteNames = array_filter(array_merge($paletteMatches[1], $paletteMatches[2]));
268  if (!empty($paletteNames)) {
269  foreach ($paletteNames as $paletteName) {
270  if (!isset(‪$GLOBALS['TCA'][$table]['palettes'][$paletteName])) {
271  continue;
272  }
273  $palette = ‪$GLOBALS['TCA'][$table]['palettes'][$paletteName];
274  switch ($positionIdentifier) {
275  case 'after':
276  case 'before':
277  if (preg_match('/\\b' . preg_quote($entityName, '/') . '\\b/', $palette['showitem']) > 0 || $entityName === 'palette:' . $paletteName) {
278  $newPosition = $positionIdentifier . ':--palette--;;' . $paletteName;
279  }
280  break;
281  case 'replace':
282  // check if fields have been added to palette before
283  if (isset($palettesChanged[$paletteName])) {
284  $fieldExists = true;
285  continue 2;
286  }
287  if (preg_match('/\\b' . preg_quote($entityName, '/') . '\\b/', $palette['showitem']) > 0) {
288  ‪self::addFieldsToPalette($table, $paletteName, $newFieldsString, $position);
289  // Memorize that we already changed this palette, in case other types also use it
290  $palettesChanged[$paletteName] = true;
291  $fieldExists = true;
292  continue 2;
293  }
294  break;
295  default:
296  // Intentionally left blank
297  }
298  }
299  }
300  }
301  }
302  if ($fieldExists === false) {
303  $typeDetails['showitem'] = ‪self::executePositionedStringInsertion(
304  $typeDetails['showitem'],
305  $newFieldsString,
306  $newPosition !== '' ? $newPosition : $position
307  );
308  }
309  }
310  unset($typeDetails);
311  }
312 
356  public static function ‪addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition = '')
357  {
358  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
359  return;
360  }
361  if (!is_array(‪$GLOBALS['TCA'][$table]['types'])) {
362  return;
363  }
364 
365  // Iterate through all types and search for the field that defines the palette to be extended
366  foreach (‪$GLOBALS['TCA'][$table]['types'] as $typeName => $typeArray) {
367  // Continue if types has no showitem at all or if requested field is not in it
368  if (!isset($typeArray['showitem']) || !str_contains($typeArray['showitem'], $field)) {
369  continue;
370  }
371  $fieldArrayWithOptions = ‪GeneralUtility::trimExplode(',', $typeArray['showitem']);
372  // Find the field we're handling
373  $newFieldStringArray = [];
374  foreach ($fieldArrayWithOptions as $fieldNumber => $fieldString) {
375  $newFieldStringArray[] = $fieldString;
376  $fieldArray = ‪GeneralUtility::trimExplode(';', $fieldString);
377  if ($fieldArray[0] !== $field) {
378  continue;
379  }
380  if (
381  isset($fieldArrayWithOptions[$fieldNumber + 1])
382  && strpos($fieldArrayWithOptions[$fieldNumber + 1], '--palette--') === 0
383  ) {
384  // Match for $field and next field is a palette - add fields to this one
385  $paletteName = ‪GeneralUtility::trimExplode(';', $fieldArrayWithOptions[$fieldNumber + 1]);
386  $paletteName = $paletteName[2];
387  ‪self::addFieldsToPalette($table, $paletteName, $addFields, $insertionPosition);
388  } else {
389  // Match for $field but next field is no palette - create a new one
390  $newPaletteName = 'generatedFor-' . $field;
391  ‪self::addFieldsToPalette($table, 'generatedFor-' . $field, $addFields, $insertionPosition);
392  $newFieldStringArray[] = '--palette--;;' . $newPaletteName;
393  }
394  }
395  ‪$GLOBALS['TCA'][$table]['types'][$typeName]['showitem'] = implode(', ', $newFieldStringArray);
396  }
397  }
398 
409  public static function ‪addFieldsToPalette($table, $palette, $addFields, $insertionPosition = '')
410  {
411  if (isset(‪$GLOBALS['TCA'][$table])) {
412  $paletteData = &‪$GLOBALS['TCA'][$table]['palettes'][$palette];
413  // If palette already exists, merge the data:
414  if (is_array($paletteData)) {
415  $paletteData['showitem'] = ‪self::executePositionedStringInsertion($paletteData['showitem'], $addFields, $insertionPosition);
416  } else {
417  $paletteData['showitem'] = ‪self::removeDuplicatesForInsertion($addFields);
418  }
419  }
420  }
421 
453  public static function ‪addTcaSelectItem($table, $field, array $item, $relativeToField = '', $relativePosition = '')
454  {
455  if (!is_string($table)) {
456  throw new \InvalidArgumentException('Given table is of type "' . gettype($table) . '" but a string is expected.', 1303236963);
457  }
458  if (!is_string($field)) {
459  throw new \InvalidArgumentException('Given field is of type "' . gettype($field) . '" but a string is expected.', 1303236964);
460  }
461  if (!is_string($relativeToField)) {
462  throw new \InvalidArgumentException('Given relative field is of type "' . gettype($relativeToField) . '" but a string is expected.', 1303236965);
463  }
464  if (!is_string($relativePosition)) {
465  throw new \InvalidArgumentException('Given relative position is of type "' . gettype($relativePosition) . '" but a string is expected.', 1303236966);
466  }
467  if ($relativePosition !== '' && $relativePosition !== 'before' && $relativePosition !== 'after' && $relativePosition !== 'replace') {
468  throw new \InvalidArgumentException('Relative position must be either empty or one of "before", "after", "replace".', 1303236967);
469  }
470  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
471  || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
472  ) {
473  throw new \RuntimeException('Given select field item list was not found.', 1303237468);
474  }
475  // Make sure item keys are integers
476  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] = array_values(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
477  if ($relativePosition !== '') {
478  // Insert at specified position
479  $matchedPosition = ‪ArrayUtility::filterByValueRecursive($relativeToField, ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
480  if (!empty($matchedPosition)) {
481  $relativeItemKey = key($matchedPosition);
482  if ($relativePosition === 'replace') {
483  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][$relativeItemKey] = $item;
484  } else {
485  if ($relativePosition === 'before') {
486  $offset = $relativeItemKey;
487  } else {
488  $offset = $relativeItemKey + 1;
489  }
490  array_splice(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'], $offset, 0, [0 => $item]);
491  }
492  } else {
493  // Insert at new item at the end of the array if relative position was not found
494  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
495  }
496  } else {
497  // Insert at new item at the end of the array
498  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
499  }
500  }
501 
512  public static function ‪addTcaSelectItemGroup(string $table, string $field, string $groupId, string $groupLabel, ?string $position = 'bottom'): void
513  {
514  if (!is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config'] ?? null)) {
515  throw new \RuntimeException('Given select field item list was not found.', 1586728563);
516  }
517  $itemGroups = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] ?? [];
518  // Group has been defined already, nothing to do
519  if (isset($itemGroups[$groupId])) {
520  return;
521  }
522  $position = (string)$position;
523  $positionGroupId = '';
524  if (str_contains($position, ':')) {
525  [$position, $positionGroupId] = explode(':', $position, 2);
526  }
527  // Referenced group was not not found, just append to the bottom
528  if (!isset($itemGroups[$positionGroupId])) {
529  $position = 'bottom';
530  }
531  switch ($position) {
532  case 'after':
533  $newItemGroups = [];
534  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
535  $newItemGroups[$existingGroupId] = $existingGroupLabel;
536  if ($positionGroupId === $existingGroupId) {
537  $newItemGroups[$groupId] = $groupLabel;
538  }
539  }
540  $itemGroups = $newItemGroups;
541  break;
542  case 'before':
543  $newItemGroups = [];
544  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
545  if ($positionGroupId === $existingGroupId) {
546  $newItemGroups[$groupId] = $groupLabel;
547  }
548  $newItemGroups[$existingGroupId] = $existingGroupLabel;
549  }
550  $itemGroups = $newItemGroups;
551  break;
552  case 'top':
553  $itemGroups = array_merge([$groupId => $groupLabel], $itemGroups);
554  break;
555  case 'bottom':
556  default:
557  $itemGroups[$groupId] = $groupLabel;
558  }
559  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] = $itemGroups;
560  }
561 
572  public static function ‪getFileFieldTCAConfig($fieldName, array $customSettingOverride = [], $allowedFileExtensions = '', $disallowedFileExtensions = '')
573  {
574  $fileFieldTCAConfig = [
575  'type' => 'inline',
576  'foreign_table' => 'sys_file_reference',
577  'foreign_field' => 'uid_foreign',
578  'foreign_sortby' => 'sorting_foreign',
579  'foreign_table_field' => 'tablenames',
580  'foreign_match_fields' => [
581  'fieldname' => $fieldName,
582  ],
583  'foreign_label' => 'uid_local',
584  'foreign_selector' => 'uid_local',
585  'overrideChildTca' => [
586  'columns' => [
587  'uid_local' => [
588  'config' => [
589  'appearance' => [
590  'elementBrowserType' => 'file',
591  'elementBrowserAllowed' => $allowedFileExtensions,
592  ],
593  ],
594  ],
595  ],
596  ],
597  'filter' => [
598  [
599  'userFunc' => FileExtensionFilter::class . '->filterInlineChildren',
600  'parameters' => [
601  'allowedFileExtensions' => $allowedFileExtensions,
602  'disallowedFileExtensions' => $disallowedFileExtensions,
603  ],
604  ],
605  ],
606  'appearance' => [
607  'useSortable' => true,
608  'headerThumbnail' => [
609  'field' => 'uid_local',
610  'height' => '45m',
611  ],
612 
613  'enabledControls' => [
614  'info' => true,
615  'new' => false,
616  'dragdrop' => true,
617  'sort' => false,
618  'hide' => true,
619  'delete' => true,
620  ],
621  ],
622  ];
623  ‪ArrayUtility::mergeRecursiveWithOverrule($fileFieldTCAConfig, $customSettingOverride);
624  return $fileFieldTCAConfig;
625  }
626 
635  public static function ‪addFieldsToUserSettings($addFields, $insertionPosition = '')
636  {
637  ‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'] = ‪self::executePositionedStringInsertion(‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'] ?? '', $addFields, $insertionPosition);
638  }
639 
657  protected static function ‪executePositionedStringInsertion($list, $insertionList, $insertionPosition = '')
658  {
659  $list = $newList = trim($list, ", \t\n\r\0\x0B");
660 
661  if ($insertionPosition !== '') {
662  [$location, $positionName] = ‪GeneralUtility::trimExplode(':', $insertionPosition, false, 2);
663  } else {
664  $location = '';
665  $positionName = '';
666  }
667 
668  if ($location !== 'replace') {
669  $insertionList = ‪self::removeDuplicatesForInsertion($insertionList, $list);
670  }
671 
672  if ($insertionList === '') {
673  return $list;
674  }
675  if ($list === '') {
676  return $insertionList;
677  }
678  if ($insertionPosition === '') {
679  return $list . ', ' . $insertionList;
680  }
681 
682  // The $insertPosition may be a palette: after:--palette--;;title
683  // In the $list the palette may contain a LLL string in between the ;;
684  // Adjust the regex to match that
685  $positionName = preg_quote($positionName, '/');
686  if (str_contains($positionName, ';;')) {
687  $positionName = str_replace(';;', ';[^;]*;', $positionName);
688  }
689 
690  $pattern = ('/(^|,\\s*)(' . $positionName . ')(;[^,$]+)?(,|$)/');
691  switch ($location) {
692  case 'after':
693  $newList = preg_replace($pattern, '$1$2$3, ' . $insertionList . '$4', $list);
694  break;
695  case 'before':
696  $newList = preg_replace($pattern, '$1' . $insertionList . ', $2$3$4', $list);
697  break;
698  case 'replace':
699  $newList = preg_replace($pattern, '$1' . $insertionList . '$4', $list);
700  break;
701  default:
702  }
703 
704  // When preg_replace did not replace anything; append the $insertionList.
705  if ($list === $newList) {
706  return $list . ', ' . $insertionList;
707  }
708  return $newList;
709  }
710 
726  protected static function ‪removeDuplicatesForInsertion($insertionList, $list = '')
727  {
728  $insertionListParts = preg_split('/\\s*,\\s*/', $insertionList);
729  $listMatches = [];
730  if ($list !== '') {
731  preg_match_all('/(?:^|,)\\s*\\b([^;,]+)\\b[^,]*/', $list, $listMatches);
732  $listMatches = $listMatches[1];
733  }
734 
735  $cleanInsertionListParts = [];
736  foreach ($insertionListParts as $fieldName) {
737  $fieldNameParts = explode(';', $fieldName, 2);
738  $cleanFieldName = $fieldNameParts[0];
739  if (
740  $cleanFieldName === '--linebreak--'
741  || (
742  !in_array($cleanFieldName, $cleanInsertionListParts, true)
743  && !in_array($cleanFieldName, $listMatches, true)
744  )
745  ) {
746  $cleanInsertionListParts[] = $fieldName;
747  }
748  }
749  return implode(', ', $cleanInsertionListParts);
750  }
751 
759  public static function ‪allowTableOnStandardPages($table)
760  {
761  ‪$GLOBALS['PAGES_TYPES']['default']['allowedTables'] ??= '';
762  ‪$GLOBALS['PAGES_TYPES']['default']['allowedTables'] .= ',' . $table;
763  }
764 
775  public static function ‪addModule($main, $sub = '', $position = '', $path = null, $moduleConfiguration = [])
776  {
777  if (!isset(‪$GLOBALS['TBE_MODULES'])) {
778  ‪$GLOBALS['TBE_MODULES'] = [];
779  }
780  // If there is already a main module by this name:
781  // Adding the submodule to the correct position:
782  if (isset(‪$GLOBALS['TBE_MODULES'][$main]) && $sub) {
783  [$place, $modRef] = array_pad(‪GeneralUtility::trimExplode(':', $position, true), 2, null);
784  $modules = ',' . ‪$GLOBALS['TBE_MODULES'][$main] . ',';
785  if ($place === null || ($modRef !== null && !GeneralUtility::inList($modules, $modRef))) {
786  $place = 'bottom';
787  }
788  $modRef = ',' . $modRef . ',';
789  if (!GeneralUtility::inList($modules, $sub)) {
790  switch (strtolower($place)) {
791  case 'after':
792  $modules = str_replace($modRef, $modRef . $sub . ',', $modules);
793  break;
794  case 'before':
795  $modules = str_replace($modRef, ',' . $sub . $modRef, $modules);
796  break;
797  case 'top':
798  $modules = $sub . $modules;
799  break;
800  case 'bottom':
801  default:
802  $modules = $modules . $sub;
803  }
804  }
805  // Re-inserting the submodule list:
806  ‪$GLOBALS['TBE_MODULES'][$main] = trim($modules, ',');
807  } elseif (!isset(‪$GLOBALS['TBE_MODULES'][$main]) && empty($sub)) {
808  // Create a new main module, respecting the order, which is only possible when the module does not exist yet
809  $conf = ‪$GLOBALS['TBE_MODULES']['_configuration'] ?? [];
810  unset(‪$GLOBALS['TBE_MODULES']['_configuration']);
811  $navigationComponents = ‪$GLOBALS['TBE_MODULES']['_navigationComponents'] ?? [];
812  unset(‪$GLOBALS['TBE_MODULES']['_navigationComponents']);
813 
814  $modules = array_keys(‪$GLOBALS['TBE_MODULES']);
815  [$place, $moduleReference] = array_pad(‪GeneralUtility::trimExplode(':', $position, true), 2, null);
816  if ($place === null || ($moduleReference !== null && !in_array($moduleReference, $modules, true))) {
817  $place = 'bottom';
818  }
819  $newModules = [];
820  switch (strtolower($place)) {
821  case 'after':
822  foreach ($modules as $existingMainModule) {
823  $newModules[$existingMainModule] = ‪$GLOBALS['TBE_MODULES'][$existingMainModule];
824  if ($moduleReference === $existingMainModule) {
825  $newModules[$main] = '';
826  }
827  }
828  break;
829  case 'before':
830  foreach ($modules as $existingMainModule) {
831  if ($moduleReference === $existingMainModule) {
832  $newModules[$main] = '';
833  }
834  $newModules[$existingMainModule] = ‪$GLOBALS['TBE_MODULES'][$existingMainModule];
835  }
836  break;
837  case 'top':
838  $newModules[$main] = '';
839  $newModules += ‪$GLOBALS['TBE_MODULES'];
840  break;
841  case 'bottom':
842  default:
843  $newModules = ‪$GLOBALS['TBE_MODULES'];
844  $newModules[$main] = '';
845  }
846  ‪$GLOBALS['TBE_MODULES'] = $newModules;
847  ‪$GLOBALS['TBE_MODULES']['_configuration'] = $conf;
848  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'] = $navigationComponents;
849  } else {
850  // Create new main modules with only one submodule, $sub (or none if $sub is blank)
851  ‪$GLOBALS['TBE_MODULES'][$main] = $sub;
852  }
853 
854  // add additional configuration
855  $fullModuleSignature = $main . ($sub ? '_' . $sub : '');
856  if (is_array($moduleConfiguration) && !empty($moduleConfiguration)) {
857  // remove default icon if an icon identifier is available
858  if (!empty($moduleConfiguration['iconIdentifier'])
859  && !empty($moduleConfiguration['icon'])
860  && $moduleConfiguration['icon'] === 'EXT:extbase/Resources/Public/Icons/Extension.svg'
861  ) {
862  unset($moduleConfiguration['icon']);
863  }
864 
865  // file_navframe is now used as SVG-based navigation component
866  // @deprecated this migration can be removed in TYPO3 v12.0
867  if (($moduleConfiguration['navigationFrameModule'] ?? '') === 'file_navframe') {
868  trigger_error('Module ' . $fullModuleSignature . ' uses "file_navframe" as "navigationFrameModule" configuration, but was migrated to the FileStorageTreeContainer navigation component. This Fallback will be removed in TYPO3 v12.0.', E_USER_DEPRECATED);
869  unset($moduleConfiguration['navigationFrameModule']);
870  $moduleConfiguration['navigationComponentId'] = 'TYPO3/CMS/Backend/Tree/FileStorageTreeContainer';
871  } elseif (isset($moduleConfiguration['navigationFrameModule']) || isset($moduleConfiguration['navFrameScript'])) {
872  trigger_error('Module ' . $fullModuleSignature . ' is using a "navigationFrameModule" configuration which renders an iframe for the navigation part, which is deprecated in favor of the navigationComponent functionality. The frame will be removed in TYPO3 v12.0.', E_USER_DEPRECATED);
873  }
874 
875  if (!empty($moduleConfiguration['icon'])) {
876  $iconPath = $moduleConfiguration['icon'];
877  if (!‪PathUtility::isExtensionPath($iconPath)) {
878  $iconPath = GeneralUtility::getFileAbsFileName($iconPath);
879  }
880  $iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
881  $iconIdentifier = 'module-' . $fullModuleSignature;
882  $iconProvider = $iconRegistry->detectIconProvider($iconPath);
883  $iconRegistry->registerIcon(
884  $iconIdentifier,
885  $iconProvider,
886  ['source' => $iconPath]
887  );
888  $moduleConfiguration['iconIdentifier'] = $iconIdentifier;
889  unset($moduleConfiguration['icon']);
890  }
891 
892  ‪$GLOBALS['TBE_MODULES']['_configuration'][$fullModuleSignature] = $moduleConfiguration;
893  }
894 
895  // Also register the module as regular route
896  $routeName = $moduleConfiguration['id'] ?? $fullModuleSignature;
897  // Build Route objects from the data
898  if (!empty($moduleConfiguration['path'])) {
899  $path = $moduleConfiguration['path'];
900  $path = '/' . ltrim($path, '/');
901  } else {
902  $path = str_replace('_', '/', $fullModuleSignature);
903  $path = '/module/' . trim($path, '/');
904  }
905 
906  $options = [
907  'module' => true,
908  'moduleName' => $fullModuleSignature,
909  'access' => !empty($moduleConfiguration['access']) ? $moduleConfiguration['access'] : 'user,group',
910  ];
911  if (!empty($moduleConfiguration['routeTarget'])) {
912  $options['target'] = $moduleConfiguration['routeTarget'];
913  }
914 
915  $router = GeneralUtility::makeInstance(Router::class);
916  $router->addRoute($routeName, GeneralUtility::makeInstance(Route::class, $path, $options));
917  }
918 
931  public static function ‪insertModuleFunction($modname, $className, $_unused, $title, $MM_key = 'function', $WS = '')
932  {
933  ‪$GLOBALS['TBE_MODULES_EXT'][$modname]['MOD_MENU'][$MM_key][$className] = [
934  'name' => $className,
935  'title' => $title,
936  'ws' => $WS,
937  ];
938  }
939 
947  public static function ‪addPageTSConfig($content)
948  {
949  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] .= '
950 [GLOBAL]
951 ' . $content;
952  }
953 
961  public static function ‪addUserTSConfig($content)
962  {
963  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig'] .= '
964 [GLOBAL]
965 ' . $content;
966  }
967 
976  public static function ‪addLLrefForTCAdescr($key, $file)
977  {
978  if (empty($key)) {
979  throw new \RuntimeException('No description key set in addLLrefForTCAdescr(). Provide it as first parameter', 1507321596);
980  }
981  if (!is_array(‪$GLOBALS['TCA_DESCR'][$key] ?? false)) {
982  ‪$GLOBALS['TCA_DESCR'][$key] = [];
983  }
984  if (!is_array(‪$GLOBALS['TCA_DESCR'][$key]['refs'] ?? false)) {
985  ‪$GLOBALS['TCA_DESCR'][$key]['refs'] = [];
986  }
987  ‪$GLOBALS['TCA_DESCR'][$key]['refs'][] = $file;
988  }
989 
998  public static function ‪addNavigationComponent($module, $componentId, $extensionKey)
999  {
1000  if (empty($extensionKey)) {
1001  throw new \RuntimeException('No extensionKey set in addNavigationComponent(). Provide it as third parameter', 1404068039);
1002  }
1003  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'][$module] = [
1004  'componentId' => $componentId,
1005  'extKey' => $extensionKey,
1006  'isCoreComponent' => false,
1007  ];
1008  }
1009 
1016  public static function ‪addCoreNavigationComponent($module, $componentId)
1017  {
1018  ‪self::addNavigationComponent($module, $componentId, 'core');
1019  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'][$module]['isCoreComponent'] = true;
1020  }
1021 
1022  /**************************************
1023  *
1024  * Adding SERVICES features
1025  *
1026  ***************************************/
1035  public static function ‪addService($extKey, $serviceType, $serviceKey, $info)
1036  {
1037  if (!$serviceType) {
1038  throw new \InvalidArgumentException('No serviceType given.', 1507321535);
1039  }
1040  if (!is_array($info)) {
1041  throw new \InvalidArgumentException('No information array given.', 1507321542);
1042  }
1043  $info['priority'] = max(0, min(100, $info['priority']));
1044  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
1045  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
1046  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
1047  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
1048  // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
1049  // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
1050  // even the activation is possible (a unix service might be possible on windows for some reasons)
1051  if (is_array(‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey] ?? false)) {
1052  // No check is done here - there might be configuration values only the service type knows about, so
1053  // we pass everything
1054  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], ‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
1055  }
1056  // OS check
1057  // Empty $os means 'not limited to one OS', therefore a check is not needed
1058  if (!empty(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available']) && (‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] ?? '') != '') {
1059  $os_type = ‪Environment::isWindows() ? 'WIN' : 'UNIX';
1060  $os = ‪GeneralUtility::trimExplode(',', strtoupper(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
1061  if (!in_array($os_type, $os, true)) {
1062  ‪self::deactivateService($serviceType, $serviceKey);
1063  }
1064  }
1065  // Convert subtype list to array for quicker access
1066  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = [];
1067  $serviceSubTypes = ‪GeneralUtility::trimExplode(',', $info['subtype']);
1068  foreach ($serviceSubTypes as $subtype) {
1069  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
1070  }
1071  }
1072 
1081  public static function ‪findService($serviceType, $serviceSubType = '', array $excludeServiceKeys = [])
1082  {
1083  $serviceKey = false;
1084  $serviceInfo = false;
1085  $priority = 0;
1086  $quality = 0;
1087  if (is_array(‪$GLOBALS['T3_SERVICES'][$serviceType])) {
1088  foreach (‪$GLOBALS['T3_SERVICES'][$serviceType] as $key => $info) {
1089  if (in_array($key, $excludeServiceKeys)) {
1090  continue;
1091  }
1092  // Select a subtype randomly
1093  // Useful to start a service by service key without knowing his subtypes - for testing purposes
1094  if ($serviceSubType === '*') {
1095  $serviceSubType = key($info['serviceSubTypes']);
1096  }
1097  // This matches empty subtype too
1098  if (($info['available'] ?? false)
1099  && (($info['subtype'] ?? null) == $serviceSubType || ($info['serviceSubTypes'][$serviceSubType] ?? false))
1100  && ($info['priority'] ?? 0) >= $priority
1101  ) {
1102  // Has a lower quality than the already found, therefore we skip this service
1103  if ($info['priority'] == $priority && $info['quality'] < $quality) {
1104  continue;
1105  }
1106  // Check if the service is available
1107  $info['available'] = ‪self::isServiceAvailable($serviceType, $key, $info);
1108  // Still available after exec check?
1109  if ($info['available']) {
1110  $serviceKey = $key;
1111  $priority = $info['priority'];
1112  $quality = $info['quality'];
1113  }
1114  }
1115  }
1116  }
1117  if ($serviceKey) {
1118  $serviceInfo = ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey];
1119  }
1120  return $serviceInfo;
1121  }
1122 
1131  public static function ‪findServiceByKey($serviceKey)
1132  {
1133  if (is_array(‪$GLOBALS['T3_SERVICES'])) {
1134  // Loop on all service types
1135  // NOTE: we don't care about the actual type, we are looking for a specific key
1136  foreach (‪$GLOBALS['T3_SERVICES'] as $serviceType => $servicesPerType) {
1137  if (isset($servicesPerType[$serviceKey])) {
1138  $serviceDetails = $servicesPerType[$serviceKey];
1139  // Test if service is available
1140  if (self::isServiceAvailable($serviceType, $serviceKey, $serviceDetails)) {
1141  // We have found the right service, return its information
1142  return $serviceDetails;
1143  }
1144  }
1145  }
1146  }
1147  throw new \TYPO3\CMS\Core\Exception('Service not found for key: ' . $serviceKey, 1319217244);
1148  }
1149 
1158  public static function ‪isServiceAvailable($serviceType, $serviceKey, $serviceDetails)
1159  {
1160  // If the service depends on external programs - check if they exists
1161  if (trim($serviceDetails['exec'] ?? '')) {
1162  $executables = ‪GeneralUtility::trimExplode(',', $serviceDetails['exec'], true);
1163  foreach ($executables as $executable) {
1164  // If at least one executable file is not available, exit early returning FALSE
1165  if (!‪CommandUtility::checkCommand($executable)) {
1166  ‪self::deactivateService($serviceType, $serviceKey);
1167  return false;
1168  }
1169  }
1170  }
1171  // The service is available
1172  return true;
1173  }
1174 
1181  public static function ‪deactivateService($serviceType, $serviceKey)
1182  {
1183  // ... maybe it's better to move non-available services to a different array??
1184  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] = false;
1185  }
1186 
1187  /**************************************
1188  *
1189  * Adding FRONTEND features
1190  *
1191  ***************************************/
1205  public static function ‪addPlugin($itemArray, $type = 'list_type', $extensionKey = null)
1206  {
1207  if (!isset($extensionKey)) {
1208  throw new \InvalidArgumentException(
1209  'No extension key could be determined when calling addPlugin()!'
1210  . LF
1211  . 'This method is meant to be called from Configuration/TCA/Overrides files. '
1212  . 'The extension key needs to be specified as third parameter. '
1213  . 'Calling it from any other place e.g. ext_localconf.php does not work and is not supported.',
1214  1404068038
1215  );
1216  }
1217  if (!isset($itemArray[2]) || !$itemArray[2]) {
1218  // @todo do we really set $itemArray[2], even if we cannot find an icon? (as that means it's set to 'EXT:foobar/')
1219  $itemArray[2] = 'EXT:' . $extensionKey . '/' . static::getExtensionIcon(static::$packageManager->getPackage($extensionKey)->getPackagePath());
1220  } elseif ($type === 'CType' && !isset(‪$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$itemArray[1]])) {
1221  // Set the type icon as well
1222  ‪$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes'][$itemArray[1]] = $itemArray[2];
1223  }
1224  if (!isset($itemArray[3])) {
1225  $itemArray[3] = 'default';
1226  }
1227  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'])) {
1228  foreach (‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'] as $k => $v) {
1229  if ((string)$v[1] === (string)$itemArray[1]) {
1230  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][$k] = $itemArray;
1231  return;
1232  }
1233  }
1234  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][] = $itemArray;
1235  }
1236  // Ensure to have at least some basic information available when editing the new type in FormEngine
1237  if ($type === 'CType' && !isset(‪$GLOBALS['TCA']['tt_content']['types'][$itemArray[1]]) && isset(‪$GLOBALS['TCA']['tt_content']['types']['header'])) {
1238  ‪$GLOBALS['TCA']['tt_content']['types'][$itemArray[1]] = ‪$GLOBALS['TCA']['tt_content']['types']['header'];
1239  }
1240  }
1241 
1252  public static function ‪addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch = 'list')
1253  {
1254  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'])) {
1255  ‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'][$piKeyToMatch . ',' . $CTypeToMatch] = $value;
1256  }
1257  }
1258 
1268  public static function ‪addToInsertRecords($table, $content_table = 'tt_content', $content_field = 'records')
1269  {
1270  if (is_array(‪$GLOBALS['TCA'][$content_table]['columns']) && isset(‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'])) {
1271  ‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'] .= ',' . $table;
1272  }
1273  }
1274 
1300  public static function ‪addPItoST43($key, $_ = '', $suffix = '', $type = 'list_type', $cacheable = false)
1301  {
1302  $cN = ‪self::getCN($key);
1303  // General plugin
1304  $pluginContent = trim('
1305 plugin.' . $cN . $suffix . ' = USER' . ($cacheable ? '' : '_INT') . '
1306 plugin.' . $cN . $suffix . '.userFunc = ' . $cN . $suffix . '->main
1307 ');
1308  ‪self::addTypoScript($key, 'setup', '
1309 # Setting ' . $key . ' plugin TypoScript
1310 ' . $pluginContent);
1311  // Add after defaultContentRendering
1312  switch ($type) {
1313  case 'list_type':
1314  $addLine = 'tt_content.list.20.' . $key . $suffix . ' = < plugin.' . $cN . $suffix;
1315  break;
1316  case 'CType':
1317  $addLine = trim('
1318 tt_content.' . $key . $suffix . ' =< lib.contentElement
1319 tt_content.' . $key . $suffix . ' {
1320  templateName = Generic
1321  20 =< plugin.' . $cN . $suffix . '
1322 }
1323 ');
1324  break;
1325  case 'header_layout':
1326  $addLine = 'lib.stdheader.10.' . $key . $suffix . ' = < plugin.' . $cN . $suffix;
1327  break;
1328  case 'includeLib':
1329  $addLine = 'page.1000 = < plugin.' . $cN . $suffix;
1330  break;
1331  default:
1332  $addLine = '';
1333  }
1334  if ($addLine) {
1335  ‪self::addTypoScript($key, 'setup', '
1336 # Setting ' . $key . ' plugin TypoScript
1337 ' . $addLine . '
1338 ', 'defaultContentRendering');
1339  }
1340  }
1341 
1352  public static function ‪addStaticFile($extKey, $path, $title)
1353  {
1354  if (!$extKey) {
1355  throw new \InvalidArgumentException('No extension key given.', 1507321291);
1356  }
1357  if (!$path) {
1358  throw new \InvalidArgumentException('No file path given.', 1507321297);
1359  }
1360  if (is_array(‪$GLOBALS['TCA']['sys_template']['columns'])) {
1361  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $path);
1362  $itemArray = [trim($title . ' (' . $extKey . ')'), $value];
1363  ‪$GLOBALS['TCA']['sys_template']['columns']['include_static_file']['config']['items'][] = $itemArray;
1364  }
1365  }
1366 
1376  public static function ‪registerPageTSConfigFile($extKey, $filePath, $title)
1377  {
1378  if (!$extKey) {
1379  throw new \InvalidArgumentException('No extension key given.', 1447789490);
1380  }
1381  if (!$filePath) {
1382  throw new \InvalidArgumentException('No file path given.', 1447789491);
1383  }
1384  if (!isset(‪$GLOBALS['TCA']['pages']['columns']) || !is_array(‪$GLOBALS['TCA']['pages']['columns'])) {
1385  throw new \InvalidArgumentException('No TCA definition for table "pages".', 1447789492);
1386  }
1387 
1388  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $filePath);
1389  $itemArray = [trim($title . ' (' . $extKey . ')'), $value];
1390  ‪$GLOBALS['TCA']['pages']['columns']['tsconfig_includes']['config']['items'][] = $itemArray;
1391  }
1392 
1400  public static function ‪addTypoScriptSetup($content)
1401  {
1402  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'] .= '
1403 [GLOBAL]
1404 ' . $content;
1405  }
1406 
1414  public static function ‪addTypoScriptConstants($content)
1415  {
1416  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'] .= '
1417 [GLOBAL]
1418 ' . $content;
1419  }
1420 
1438  public static function ‪addTypoScript(string $key, string $type, string $content, $afterStaticUid = 0)
1439  {
1440  if ($type !== 'setup' && $type !== 'constants') {
1441  throw new \InvalidArgumentException('Argument $type must be set to either "setup" or "constants" when calling addTypoScript from extension "' . $key . '"', 1507321200);
1442  }
1443  $content = '
1444 
1445 [GLOBAL]
1446 #############################################
1447 ## TypoScript added by extension "' . $key . '"
1448 #############################################
1449 
1450 ' . $content;
1451  if ($afterStaticUid) {
1452  // If 'content (default)' is targeted (static uid 43),
1453  // the content is added after typoscript of type contentRendering, eg. fluid_styled_content, see EXT:frontend/TemplateService for more information on how the code is parsed
1454  if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
1455  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'])) {
1456  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] = '';
1457  }
1458  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
1459  } else {
1460  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid])) {
1461  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] = '';
1462  }
1463  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
1464  }
1465  } else {
1466  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type])) {
1467  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] = '';
1468  }
1469  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
1470  }
1471  }
1472 
1473  /***************************************
1474  *
1475  * Internal extension management methods
1476  *
1477  ***************************************/
1486  public static function ‪getExtensionIcon($extensionPath, $returnFullPath = false)
1487  {
1488  $icon = '';
1489  $locationsToCheckFor = [
1490  'Resources/Public/Icons/Extension.svg',
1491  'Resources/Public/Icons/Extension.png',
1492  'Resources/Public/Icons/Extension.gif',
1493  'ext_icon.svg',
1494  'ext_icon.png',
1495  'ext_icon.gif',
1496  ];
1497  foreach ($locationsToCheckFor as $fileLocation) {
1498  if (file_exists($extensionPath . $fileLocation)) {
1499  $icon = $fileLocation;
1500  break;
1501  }
1502  }
1503  return $returnFullPath ? $extensionPath . $icon : $icon;
1504  }
1505 
1518  public static function ‪loadExtLocalconf($allowCaching = true, FrontendInterface $codeCache = null)
1519  {
1520  if ($allowCaching) {
1521  $codeCache = $codeCache ?? ‪self::getCacheManager()->‪getCache('core');
1522  $cacheIdentifier = ‪self::getExtLocalconfCacheIdentifier();
1523  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1524  if (!$hasCache) {
1527  }
1528  } else {
1530  }
1531  }
1536  protected static function ‪loadSingleExtLocalconfFiles()
1537  {
1538  foreach (static::$packageManager->getActivePackages() as $package) {
1539  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1540  if (@file_exists($extLocalconfPath)) {
1541  require $extLocalconfPath;
1542  }
1543  }
1544  }
1545 
1552  public static function ‪createExtLocalconfCacheEntry(‪FrontendInterface $codeCache)
1553  {
1554  $phpCodeToCache = [];
1555  // Set same globals as in loadSingleExtLocalconfFiles()
1556  $phpCodeToCache[] = '';
1559  $phpCodeToCache[] = '';
1560  // Iterate through loaded extensions and add ext_localconf content
1561  foreach (static::$packageManager->getActivePackages() as $package) {
1562  $extensionKey = $package->getPackageKey();
1563  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1564  if (@file_exists($extLocalconfPath)) {
1565  // Include a header per extension to make the cache file more readable
1566  $phpCodeToCache[] = '';
1570  $phpCodeToCache[] = '';
1571  // Add ext_localconf.php content of extension
1572  $phpCodeToCache[] = 'namespace {';
1573  $phpCodeToCache[] = trim((string)file_get_contents($extLocalconfPath));
1574  $phpCodeToCache[] = '}';
1575  $phpCodeToCache[] = '';
1576  $phpCodeToCache[] = '';
1577  }
1578  }
1579  $phpCodeToCache = implode(LF, $phpCodeToCache);
1580  // Remove all start and ending php tags from content
1581  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1582  $phpCodeToCache = preg_replace('/declare\\s?+\\(\\s?+strict_types\\s?+=\\s?+1\\s?+\\);/is', '', (string)$phpCodeToCache);
1583  $codeCache->‪set(self::getExtLocalconfCacheIdentifier(), $phpCodeToCache);
1584  }
1585 
1591  protected static function ‪getExtLocalconfCacheIdentifier()
1592  {
1593  return (new PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('ext_localconf')->toString();
1594  }
1595 
1609  public static function ‪loadBaseTca($allowCaching = true, FrontendInterface $codeCache = null)
1610  {
1611  if ($allowCaching) {
1612  $codeCache = $codeCache ?? ‪self::getCacheManager()->‪getCache('core');
1613  $cacheIdentifier = static::getBaseTcaCacheIdentifier();
1614  $cacheData = $codeCache->require($cacheIdentifier);
1615  if ($cacheData) {
1616  ‪$GLOBALS['TCA'] = $cacheData['tca'];
1617  // @deprecated remove categoryRegistry in v12
1618  GeneralUtility::setSingletonInstance(
1619  CategoryRegistry::class,
1620  unserialize(
1621  $cacheData['categoryRegistry'],
1622  ['allowed_classes' => [CategoryRegistry::class]]
1623  )
1624  );
1625  } else {
1626  static::buildBaseTcaFromSingleFiles();
1627  static::createBaseTcaCacheFile($codeCache);
1628  }
1629  } else {
1630  static::buildBaseTcaFromSingleFiles();
1631  }
1632  }
1633 
1642  public static function ‪buildBaseTcaFromSingleFiles()
1643  {
1644  ‪$GLOBALS['TCA'] = [];
1645 
1646  $activePackages = static::$packageManager->getActivePackages();
1647 
1648  // First load "full table" files from Configuration/TCA
1649  foreach ($activePackages as $package) {
1650  try {
1651  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA');
1652  } catch (\InvalidArgumentException $e) {
1653  // No such directory in this package
1654  continue;
1655  }
1656  foreach (‪$finder as $fileInfo) {
1657  $tcaOfTable = require $fileInfo->getPathname();
1658  if (is_array($tcaOfTable)) {
1659  $tcaTableName = substr($fileInfo->getBasename(), 0, -4);
1660  ‪$GLOBALS['TCA'][$tcaTableName] = $tcaOfTable;
1661  }
1662  }
1663  }
1664 
1665  // Apply category stuff
1666  // @deprecated since v11, can be removed in v12
1668 
1669  // Execute override files from Configuration/TCA/Overrides
1670  foreach ($activePackages as $package) {
1671  try {
1672  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA/Overrides');
1673  } catch (\InvalidArgumentException $e) {
1674  // No such directory in this package
1675  continue;
1676  }
1677  foreach (‪$finder as $fileInfo) {
1678  require $fileInfo->getPathname();
1679  }
1680  }
1681 
1682  // Call the TcaMigration and log any deprecations.
1683  $tcaMigration = GeneralUtility::makeInstance(TcaMigration::class);
1684  ‪$GLOBALS['TCA'] = $tcaMigration->migrate(‪$GLOBALS['TCA']);
1685  $messages = $tcaMigration->getMessages();
1686  if (!empty($messages)) {
1687  $context = 'Automatic TCA migration done during bootstrap. Please adapt TCA accordingly, these migrations'
1688  . ' will be removed. The backend module "Configuration -> TCA" shows the modified values.'
1689  . ' Please adapt these areas:';
1690  array_unshift($messages, $context);
1691  trigger_error(implode(LF, $messages), E_USER_DEPRECATED);
1692  }
1693 
1694  // TCA preparation
1695  $tcaPreparation = GeneralUtility::makeInstance(TcaPreparation::class);
1696  ‪$GLOBALS['TCA'] = $tcaPreparation->prepare(‪$GLOBALS['TCA']);
1697 
1698  static::dispatchTcaIsBeingBuiltEvent(‪$GLOBALS['TCA']);
1699  }
1700 
1706  protected static function ‪dispatchTcaIsBeingBuiltEvent(array ‪$tca)
1707  {
1708  ‪$GLOBALS['TCA'] = static::$eventDispatcher->dispatch(new AfterTcaCompilationEvent(‪$tca))->getTca();
1709  }
1710 
1718  public static function ‪createBaseTcaCacheFile(FrontendInterface $codeCache)
1719  {
1720  // @deprecated Remove 'categoryRegistry' in v12
1721  $codeCache->set(
1722  static::getBaseTcaCacheIdentifier(),
1723  'return '
1724  . var_export(['tca' => ‪$GLOBALS['TCA'], 'categoryRegistry' => serialize(‪CategoryRegistry::getInstance())], true)
1725  . ';'
1726  );
1727  }
1728 
1734  protected static function ‪getBaseTcaCacheIdentifier()
1735  {
1736  return (new PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('tca_base')->toString();
1737  }
1738 
1750  public static function ‪loadExtTables($allowCaching = true, FrontendInterface $codeCache = null)
1751  {
1752  if ($allowCaching && !self::$extTablesWasReadFromCacheOnce) {
1753  self::$extTablesWasReadFromCacheOnce = true;
1754  $cacheIdentifier = ‪self::getExtTablesCacheIdentifier();
1755  $codeCache = $codeCache ?? ‪self::getCacheManager()->‪getCache('core');
1756  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1757  if (!$hasCache) {
1760  }
1761  } else {
1763  }
1764  }
1769  protected static function ‪loadSingleExtTablesFiles()
1770  {
1771  // Load each ext_tables.php file of loaded extensions
1772  foreach (static::$packageManager->getActivePackages() as $package) {
1773  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1774  if (@file_exists($extTablesPath)) {
1775  require $extTablesPath;
1776  }
1777  }
1778  }
1779 
1786  public static function ‪createExtTablesCacheEntry(‪FrontendInterface $codeCache)
1787  {
1788  $phpCodeToCache = [];
1789  // Set same globals as in loadSingleExtTablesFiles()
1790  $phpCodeToCache[] = '';
1793  $phpCodeToCache[] = '';
1794  // Iterate through loaded extensions and add ext_tables content
1795  foreach (static::$packageManager->getActivePackages() as $package) {
1796  $extensionKey = $package->getPackageKey();
1797  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1798  if (@file_exists($extTablesPath)) {
1799  // Include a header per extension to make the cache file more readable
1800  $phpCodeToCache[] = '';
1804  $phpCodeToCache[] = '';
1805  // Add ext_tables.php content of extension
1806  $phpCodeToCache[] = 'namespace {';
1807  $phpCodeToCache[] = trim((string)file_get_contents($extTablesPath));
1808  $phpCodeToCache[] = '}';
1809  $phpCodeToCache[] = '';
1810  }
1811  }
1812  $phpCodeToCache = implode(LF, $phpCodeToCache);
1813  // Remove all start and ending php tags from content
1814  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1815  $phpCodeToCache = preg_replace('/declare\\s?+\\(\\s?+strict_types\\s?+=\\s?+1\\s?+\\);/is', '', (string)$phpCodeToCache);
1816  $codeCache->‪set(self::getExtTablesCacheIdentifier(), $phpCodeToCache);
1817  }
1818 
1824  protected static function ‪getExtTablesCacheIdentifier()
1825  {
1826  return (new PackageDependentCacheIdentifier(self::$packageManager))->withPrefix('ext_tables')->toString();
1827  }
1828 
1834  public static function ‪getLoadedExtensionListArray()
1835  {
1836  return array_keys(static::$packageManager->getActivePackages());
1837  }
1838 
1848  public static function ‪loadExtension($extensionKey)
1849  {
1850  if (static::$packageManager->isPackageActive($extensionKey)) {
1851  throw new \RuntimeException('Extension already loaded', 1342345486);
1852  }
1853  static::$packageManager->activatePackage($extensionKey);
1854  }
1855 
1865  public static function ‪unloadExtension($extensionKey)
1866  {
1867  if (!static::$packageManager->isPackageActive($extensionKey)) {
1868  throw new \RuntimeException('Extension not loaded', 1342345487);
1869  }
1870  static::$packageManager->deactivatePackage($extensionKey);
1871  }
1872 
1885  public static function ‪makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = [], $override = false)
1886  {
1887  trigger_error(
1888  __CLASS__ . '::makeCategorizable() is deprecated and will be removed in v12. Use the TCA type "category" instead.',
1889  E_USER_DEPRECATED
1890  );
1891 
1892  // Update the category registry
1893  $result = ‪CategoryRegistry::getInstance()->‪add($extensionKey, $tableName, $fieldName, $options, $override);
1894  if ($result === false) {
1895  GeneralUtility::makeInstance(LogManager::class)
1896  ->getLogger(__CLASS__)
1897  ->warning(sprintf(
1898  CategoryRegistry::class . ': no category registered for table "%s". Key was already registered.',
1899  $tableName
1900  ));
1901  }
1902  }
1903 }
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtTables
‪static loadExtTables($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1746
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\dispatchTcaIsBeingBuiltEvent
‪static dispatchTcaIsBeingBuiltEvent(array $tca)
Definition: ExtensionManagementUtility.php:1702
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:999
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptConstants
‪static addTypoScriptConstants($content)
Definition: ExtensionManagementUtility.php:1410
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addModule
‪static addModule($main, $sub='', $position='', $path=null, $moduleConfiguration=[])
Definition: ExtensionManagementUtility.php:771
‪TYPO3\CMS\Core\Migrations\TcaMigration
Definition: TcaMigration.php:26
‪TYPO3\CMS\Core\Cache\CacheManager\getCache
‪FrontendInterface getCache($identifier)
Definition: CacheManager.php:142
‪$finder
‪if(PHP_SAPI !=='cli') $finder
Definition: header-comment.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtTablesCacheIdentifier
‪static string getExtTablesCacheIdentifier()
Definition: ExtensionManagementUtility.php:1820
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\unloadExtension
‪static unloadExtension($extensionKey)
Definition: ExtensionManagementUtility.php:1861
‪TYPO3\CMS\Core\Utility\CommandUtility\checkCommand
‪static bool checkCommand($cmd, $handler='')
Definition: CommandUtility.php:164
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptSetup
‪static addTypoScriptSetup($content)
Definition: ExtensionManagementUtility.php:1396
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getFileFieldTCAConfig
‪static array getFileFieldTCAConfig($fieldName, array $customSettingOverride=[], $allowedFileExtensions='', $disallowedFileExtensions='')
Definition: ExtensionManagementUtility.php:568
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\allowTableOnStandardPages
‪static allowTableOnStandardPages($table)
Definition: ExtensionManagementUtility.php:755
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static bool isExtensionPath(string $path)
Definition: PathUtility.php:121
‪TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent
Definition: AfterTcaCompilationEvent.php:27
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtLocalconfCacheEntry
‪static createExtLocalconfCacheEntry(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1548
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtension
‪static loadExtension($extensionKey)
Definition: ExtensionManagementUtility.php:1844
‪TYPO3\CMS\Core\Package\Cache\PackageDependentCacheIdentifier
Definition: PackageDependentCacheIdentifier.php:30
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$eventDispatcher
‪static EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementUtility.php:73
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtLocalconfFiles
‪static loadSingleExtLocalconfFiles()
Definition: ExtensionManagementUtility.php:1532
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToPalette
‪static addFieldsToPalette($table, $palette, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:405
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItem
‪static addTcaSelectItem($table, $field, array $item, $relativeToField='', $relativePosition='')
Definition: ExtensionManagementUtility.php:449
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:318
‪TYPO3\CMS\Core\Utility
Definition: ArrayUtility.php:16
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getBaseTcaCacheIdentifier
‪static string getBaseTcaCacheIdentifier()
Definition: ExtensionManagementUtility.php:1730
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPlugin
‪static addPlugin($itemArray, $type='list_type', $extensionKey=null)
Definition: ExtensionManagementUtility.php:1201
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToAllTCAtypes
‪static addToAllTCAtypes($table, $newFieldsString, $typeList='', $position='')
Definition: ExtensionManagementUtility.php:224
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtTablesCacheEntry
‪static createExtTablesCacheEntry(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1782
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTCAcolumns
‪static addTCAcolumns($table, $columnArray)
Definition: ExtensionManagementUtility.php:203
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItemGroup
‪static addTcaSelectItemGroup(string $table, string $field, string $groupId, string $groupLabel, ?string $position='bottom')
Definition: ExtensionManagementUtility.php:508
‪TYPO3\CMS\Backend\Routing\Route
Definition: Route.php:24
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPItoST43
‪static addPItoST43($key, $_='', $suffix='', $type='list_type', $cacheable=false)
Definition: ExtensionManagementUtility.php:1296
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isServiceAvailable
‪static bool isServiceAvailable($serviceType, $serviceKey, $serviceDetails)
Definition: ExtensionManagementUtility.php:1154
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToAllPalettesOfField
‪static addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:352
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPiFlexFormValue
‪static addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch='list')
Definition: ExtensionManagementUtility.php:1248
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\makeCategorizable
‪static makeCategorizable($extensionKey, $tableName, $fieldName='categories', array $options=[], $override=false)
Definition: ExtensionManagementUtility.php:1881
‪TYPO3\CMS\Core\Category\CategoryRegistry\getInstance
‪static CategoryRegistry getInstance()
Definition: CategoryRegistry.php:53
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$extTablesWasReadFromCacheOnce
‪static bool $extTablesWasReadFromCacheOnce
Definition: ExtensionManagementUtility.php:53
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\deactivateService
‪static deactivateService($serviceType, $serviceKey)
Definition: ExtensionManagementUtility.php:1177
‪TYPO3\CMS\Core\Category\CategoryRegistry
Definition: CategoryRegistry.php:30
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setPackageManager
‪static setPackageManager(PackageManager $packageManager)
Definition: ExtensionManagementUtility.php:66
‪TYPO3\CMS\Core\Utility\ArrayUtility\filterByValueRecursive
‪static array filterByValueRecursive($needle='', array $haystack=[])
Definition: ArrayUtility.php:104
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtensionVersion
‪static string getExtensionVersion($key)
Definition: ExtensionManagementUtility.php:172
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCacheManager
‪static CacheManager getCacheManager()
Definition: ExtensionManagementUtility.php:95
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addUserTSConfig
‪static addUserTSConfig($content)
Definition: ExtensionManagementUtility.php:957
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\resolvePackagePath
‪static string resolvePackagePath(string $path)
Definition: ExtensionManagementUtility.php:129
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addStaticFile
‪static addStaticFile($extKey, $path, $title)
Definition: ExtensionManagementUtility.php:1348
‪TYPO3\CMS\Core\Preparations\TcaPreparation
Definition: TcaPreparation.php:31
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addLLrefForTCAdescr
‪static addLLrefForTCAdescr($key, $file)
Definition: ExtensionManagementUtility.php:972
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\executePositionedStringInsertion
‪static string executePositionedStringInsertion($list, $insertionList, $insertionPosition='')
Definition: ExtensionManagementUtility.php:653
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtTablesFiles
‪static loadSingleExtTablesFiles()
Definition: ExtensionManagementUtility.php:1765
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:32
‪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:927
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter
Definition: FileExtensionFilter.php:28
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCN
‪static string getCN($key)
Definition: ExtensionManagementUtility.php:157
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$packageManager
‪static PackageManager $packageManager
Definition: ExtensionManagementUtility.php:57
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\registerPageTSConfigFile
‪static registerPageTSConfigFile($extKey, $filePath, $title)
Definition: ExtensionManagementUtility.php:1372
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findServiceByKey
‪static array findServiceByKey($serviceKey)
Definition: ExtensionManagementUtility.php:1127
‪TYPO3\CMS\Core\Category\CategoryRegistry\add
‪bool add($extensionKey, $tableName, $fieldName='categories', array $options=[], $override=false)
Definition: CategoryRegistry.php:86
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScript
‪static addTypoScript(string $key, string $type, string $content, $afterStaticUid=0)
Definition: ExtensionManagementUtility.php:1434
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:33
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:43
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPageTSConfig
‪static addPageTSConfig($content)
Definition: ExtensionManagementUtility.php:943
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToUserSettings
‪static addFieldsToUserSettings($addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:631
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createBaseTcaCacheFile
‪static createBaseTcaCacheFile(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1714
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:142
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadBaseTca
‪static loadBaseTca($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1605
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getLoadedExtensionListArray
‪static array getLoadedExtensionListArray()
Definition: ExtensionManagementUtility.php:1830
‪TYPO3\CMS\Core\Package\Exception
Definition: InvalidPackageKeyException.php:16
‪TYPO3\CMS\Core\Category\CategoryRegistry\applyTcaForPreRegisteredTables
‪applyTcaForPreRegisteredTables()
Definition: CategoryRegistry.php:216
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtLocalconfCacheIdentifier
‪static string getExtLocalconfCacheIdentifier()
Definition: ExtensionManagementUtility.php:1587
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\setEventDispatcher
‪static setEventDispatcher(EventDispatcherInterface $eventDispatcher)
Definition: ExtensionManagementUtility.php:81
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface\set
‪set($entryIdentifier, $data, array $tags=[], $lifetime=null)
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtensionIcon
‪static string getExtensionIcon($extensionPath, $returnFullPath=false)
Definition: ExtensionManagementUtility.php:1482
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addNavigationComponent
‪static addNavigationComponent($module, $componentId, $extensionKey)
Definition: ExtensionManagementUtility.php:994
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtLocalconf
‪static loadExtLocalconf($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1514
‪TYPO3\CMS\Backend\Routing\Router
Definition: Router.php:39
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToInsertRecords
‪static addToInsertRecords($table, $content_table='tt_content', $content_field='records')
Definition: ExtensionManagementUtility.php:1264
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\removeDuplicatesForInsertion
‪static string removeDuplicatesForInsertion($insertionList, $list='')
Definition: ExtensionManagementUtility.php:722
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findService
‪static mixed findService($serviceType, $serviceSubType='', array $excludeServiceKeys=[])
Definition: ExtensionManagementUtility.php:1077
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addService
‪static addService($extKey, $serviceType, $serviceKey, $info)
Definition: ExtensionManagementUtility.php:1031
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\buildBaseTcaFromSingleFiles
‪static buildBaseTcaFromSingleFiles()
Definition: ExtensionManagementUtility.php:1638
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$cacheManager
‪static CacheManager $cacheManager
Definition: ExtensionManagementUtility.php:88
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addCoreNavigationComponent
‪static addCoreNavigationComponent($module, $componentId)
Definition: ExtensionManagementUtility.php:1012