‪TYPO3CMS  10.4
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 
131  public static function ‪extPath($key, $script = '')
132  {
133  if (!static::$packageManager->isPackageActive($key)) {
134  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension key "' . $key . '" is NOT loaded!', 1365429656);
135  }
136  return static::$packageManager->getPackage($key)->getPackagePath() . $script;
137  }
138 
146  public static function ‪getCN($key)
147  {
148  return strpos($key, 'user_') === 0 ? 'user_' . str_replace('_', '', substr($key, 5)) : 'tx_' . str_replace('_', '', $key);
149  }
150 
161  public static function ‪getExtensionVersion($key)
162  {
163  if (!is_string($key) || empty($key)) {
164  throw new \InvalidArgumentException('Extension key must be a non-empty string.', 1294586096);
165  }
166  if (!static::isLoaded($key)) {
167  return '';
168  }
169  $version = static::$packageManager->getPackage($key)->getPackageMetaData()->getVersion();
170  if (empty($version)) {
171  throw new Exception('Version number in composer manifest of package "' . $key . '" is missing or invalid', 1395614959);
172  }
173  return $version;
174  }
175 
176  /**************************************
177  *
178  * Adding BACKEND features
179  * (related to core features)
180  *
181  ***************************************/
192  public static function ‪addTCAcolumns($table, $columnArray)
193  {
194  if (is_array($columnArray) && is_array(‪$GLOBALS['TCA'][$table]) && is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
195  // Candidate for array_merge() if integer-keys will some day make trouble...
196  ‪$GLOBALS['TCA'][$table]['columns'] = array_merge(‪$GLOBALS['TCA'][$table]['columns'], $columnArray);
197  }
198  }
199 
213  public static function ‪addToAllTCAtypes($table, $newFieldsString, $typeList = '', $position = '')
214  {
215  $newFieldsString = trim($newFieldsString);
216  if ($newFieldsString === '' || !is_array(‪$GLOBALS['TCA'][$table]['types'] ?? false)) {
217  return;
218  }
219  if ($position !== '') {
220  [$positionIdentifier, $entityName] = ‪GeneralUtility::trimExplode(':', $position);
221  } else {
222  $positionIdentifier = '';
223  $entityName = '';
224  }
225  $palettesChanged = [];
226 
227  foreach (‪$GLOBALS['TCA'][$table]['types'] as $type => &$typeDetails) {
228  // skip if we don't want to add the field for this type
229  if ($typeList !== '' && !GeneralUtility::inList($typeList, $type)) {
230  continue;
231  }
232  // skip if fields were already added
233  if (!isset($typeDetails['showitem'])) {
234  continue;
235  }
236 
237  $fieldArray = ‪GeneralUtility::trimExplode(',', $typeDetails['showitem'], true);
238  if (in_array($newFieldsString, $fieldArray, true)) {
239  continue;
240  }
241 
242  $fieldExists = false;
243  $newPosition = '';
244  if (is_array(‪$GLOBALS['TCA'][$table]['palettes'] ?? false)) {
245  // Get the palette names used in current showitem
246  $paletteCount = preg_match_all('/(?:^|,) # Line start or a comma
247  (?:
248  \\s*\\-\\-palette\\-\\-;[^;]*;([^,$]*)| # --palette--;label;paletteName
249  \\s*\\b[^;,]+\\b(?:;[^;]*;([^;,]+))?[^,]* # field;label;paletteName
250  )/x', $typeDetails['showitem'], $paletteMatches);
251  if ($paletteCount > 0) {
252  $paletteNames = array_filter(array_merge($paletteMatches[1], $paletteMatches[2]));
253  if (!empty($paletteNames)) {
254  foreach ($paletteNames as $paletteName) {
255  if (!isset(‪$GLOBALS['TCA'][$table]['palettes'][$paletteName])) {
256  continue;
257  }
258  $palette = ‪$GLOBALS['TCA'][$table]['palettes'][$paletteName];
259  switch ($positionIdentifier) {
260  case 'after':
261  case 'before':
262  if (preg_match('/\\b' . $entityName . '\\b/', $palette['showitem']) > 0) {
263  $newPosition = $positionIdentifier . ':--palette--;;' . $paletteName;
264  }
265  break;
266  case 'replace':
267  // check if fields have been added to palette before
268  if (isset($palettesChanged[$paletteName])) {
269  $fieldExists = true;
270  continue 2;
271  }
272  if (preg_match('/\\b' . $entityName . '\\b/', $palette['showitem']) > 0) {
273  ‪self::addFieldsToPalette($table, $paletteName, $newFieldsString, $position);
274  // Memorize that we already changed this palette, in case other types also use it
275  $palettesChanged[$paletteName] = true;
276  $fieldExists = true;
277  continue 2;
278  }
279  break;
280  default:
281  // Intentionally left blank
282  }
283  }
284  }
285  }
286  }
287  if ($fieldExists === false) {
288  $typeDetails['showitem'] = ‪self::executePositionedStringInsertion(
289  $typeDetails['showitem'],
290  $newFieldsString,
291  $newPosition !== '' ? $newPosition : $position
292  );
293  }
294  }
295  unset($typeDetails);
296  }
297 
341  public static function ‪addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition = '')
342  {
343  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
344  return;
345  }
346  if (!is_array(‪$GLOBALS['TCA'][$table]['types'])) {
347  return;
348  }
349 
350  // Iterate through all types and search for the field that defines the palette to be extended
351  foreach (‪$GLOBALS['TCA'][$table]['types'] as $typeName => $typeArray) {
352  // Continue if types has no showitem at all or if requested field is not in it
353  if (!isset($typeArray['showitem']) || strpos($typeArray['showitem'], $field) === false) {
354  continue;
355  }
356  $fieldArrayWithOptions = ‪GeneralUtility::trimExplode(',', $typeArray['showitem']);
357  // Find the field we're handling
358  $newFieldStringArray = [];
359  foreach ($fieldArrayWithOptions as $fieldNumber => $fieldString) {
360  $newFieldStringArray[] = $fieldString;
361  $fieldArray = ‪GeneralUtility::trimExplode(';', $fieldString);
362  if ($fieldArray[0] !== $field) {
363  continue;
364  }
365  if (
366  isset($fieldArrayWithOptions[$fieldNumber + 1])
367  && strpos($fieldArrayWithOptions[$fieldNumber + 1], '--palette--') === 0
368  ) {
369  // Match for $field and next field is a palette - add fields to this one
370  $paletteName = ‪GeneralUtility::trimExplode(';', $fieldArrayWithOptions[$fieldNumber + 1]);
371  $paletteName = $paletteName[2];
372  ‪self::addFieldsToPalette($table, $paletteName, $addFields, $insertionPosition);
373  } else {
374  // Match for $field but next field is no palette - create a new one
375  $newPaletteName = 'generatedFor-' . $field;
376  ‪self::addFieldsToPalette($table, 'generatedFor-' . $field, $addFields, $insertionPosition);
377  $newFieldStringArray[] = '--palette--;;' . $newPaletteName;
378  }
379  }
380  ‪$GLOBALS['TCA'][$table]['types'][$typeName]['showitem'] = implode(', ', $newFieldStringArray);
381  }
382  }
383 
394  public static function ‪addFieldsToPalette($table, $palette, $addFields, $insertionPosition = '')
395  {
396  if (isset(‪$GLOBALS['TCA'][$table])) {
397  $paletteData = &‪$GLOBALS['TCA'][$table]['palettes'][$palette];
398  // If palette already exists, merge the data:
399  if (is_array($paletteData)) {
400  $paletteData['showitem'] = ‪self::executePositionedStringInsertion($paletteData['showitem'], $addFields, $insertionPosition);
401  } else {
402  $paletteData['showitem'] = ‪self::removeDuplicatesForInsertion($addFields);
403  }
404  }
405  }
406 
435  public static function ‪addTcaSelectItem($table, $field, array $item, $relativeToField = '', $relativePosition = '')
436  {
437  if (!is_string($table)) {
438  throw new \InvalidArgumentException('Given table is of type "' . gettype($table) . '" but a string is expected.', 1303236963);
439  }
440  if (!is_string($field)) {
441  throw new \InvalidArgumentException('Given field is of type "' . gettype($field) . '" but a string is expected.', 1303236964);
442  }
443  if (!is_string($relativeToField)) {
444  throw new \InvalidArgumentException('Given relative field is of type "' . gettype($relativeToField) . '" but a string is expected.', 1303236965);
445  }
446  if (!is_string($relativePosition)) {
447  throw new \InvalidArgumentException('Given relative position is of type "' . gettype($relativePosition) . '" but a string is expected.', 1303236966);
448  }
449  if ($relativePosition !== '' && $relativePosition !== 'before' && $relativePosition !== 'after' && $relativePosition !== 'replace') {
450  throw new \InvalidArgumentException('Relative position must be either empty or one of "before", "after", "replace".', 1303236967);
451  }
452  if (!isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
453  || !is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])
454  ) {
455  throw new \RuntimeException('Given select field item list was not found.', 1303237468);
456  }
457  // Make sure item keys are integers
458  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] = array_values(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
459  if ($relativePosition !== '') {
460  // Insert at specified position
461  $matchedPosition = ‪ArrayUtility::filterByValueRecursive($relativeToField, ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
462  if (!empty($matchedPosition)) {
463  $relativeItemKey = key($matchedPosition);
464  if ($relativePosition === 'replace') {
465  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][$relativeItemKey] = $item;
466  } else {
467  if ($relativePosition === 'before') {
468  $offset = $relativeItemKey;
469  } else {
470  $offset = $relativeItemKey + 1;
471  }
472  array_splice(‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'], $offset, 0, [0 => $item]);
473  }
474  } else {
475  // Insert at new item at the end of the array if relative position was not found
476  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
477  }
478  } else {
479  // Insert at new item at the end of the array
480  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
481  }
482  }
483 
494  public static function ‪addTcaSelectItemGroup(string $table, string $field, string $groupId, string $groupLabel, ?string $position = 'bottom'): void
495  {
496  if (!is_array(‪$GLOBALS['TCA'][$table]['columns'][$field]['config'] ?? null)) {
497  throw new \RuntimeException('Given select field item list was not found.', 1586728563);
498  }
499  $itemGroups = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] ?? [];
500  // Group has been defined already, nothing to do
501  if (isset($itemGroups[$groupId])) {
502  return;
503  }
504  $position = (string)$position;
505  $positionGroupId = '';
506  if (strpos($position, ':') !== false) {
507  [$position, $positionGroupId] = explode(':', $position, 2);
508  }
509  // Referenced group was not not found, just append to the bottom
510  if (!isset($itemGroups[$positionGroupId])) {
511  $position = 'bottom';
512  }
513  switch ($position) {
514  case 'after':
515  $newItemGroups = [];
516  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
517  $newItemGroups[$existingGroupId] = $existingGroupLabel;
518  if ($positionGroupId === $existingGroupId) {
519  $newItemGroups[$groupId] = $groupLabel;
520  }
521  }
522  $itemGroups = $newItemGroups;
523  break;
524  case 'before':
525  $newItemGroups = [];
526  foreach ($itemGroups as $existingGroupId => $existingGroupLabel) {
527  if ($positionGroupId === $existingGroupId) {
528  $newItemGroups[$groupId] = $groupLabel;
529  }
530  $newItemGroups[$existingGroupId] = $existingGroupLabel;
531  }
532  $itemGroups = $newItemGroups;
533  break;
534  case 'top':
535  $itemGroups = array_merge([$groupId => $groupLabel], $itemGroups);
536  break;
537  case 'bottom':
538  default:
539  $itemGroups[$groupId] = $groupLabel;
540  }
541  ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['itemGroups'] = $itemGroups;
542  }
543 
554  public static function ‪getFileFieldTCAConfig($fieldName, array $customSettingOverride = [], $allowedFileExtensions = '', $disallowedFileExtensions = '')
555  {
556  $fileFieldTCAConfig = [
557  'type' => 'inline',
558  'foreign_table' => 'sys_file_reference',
559  'foreign_field' => 'uid_foreign',
560  'foreign_sortby' => 'sorting_foreign',
561  'foreign_table_field' => 'tablenames',
562  'foreign_match_fields' => [
563  'fieldname' => $fieldName
564  ],
565  'foreign_label' => 'uid_local',
566  'foreign_selector' => 'uid_local',
567  'overrideChildTca' => [
568  'columns' => [
569  'uid_local' => [
570  'config' => [
571  'appearance' => [
572  'elementBrowserType' => 'file',
573  'elementBrowserAllowed' => $allowedFileExtensions
574  ],
575  ],
576  ],
577  ],
578  ],
579  'filter' => [
580  [
581  'userFunc' => FileExtensionFilter::class . '->filterInlineChildren',
582  'parameters' => [
583  'allowedFileExtensions' => $allowedFileExtensions,
584  'disallowedFileExtensions' => $disallowedFileExtensions
585  ]
586  ]
587  ],
588  'appearance' => [
589  'useSortable' => true,
590  'headerThumbnail' => [
591  'field' => 'uid_local',
592  'height' => '45m',
593  ],
594 
595  'enabledControls' => [
596  'info' => true,
597  'new' => false,
598  'dragdrop' => true,
599  'sort' => false,
600  'hide' => true,
601  'delete' => true,
602  ],
603  ]
604  ];
605  ‪ArrayUtility::mergeRecursiveWithOverrule($fileFieldTCAConfig, $customSettingOverride);
606  return $fileFieldTCAConfig;
607  }
608 
617  public static function ‪addFieldsToUserSettings($addFields, $insertionPosition = '')
618  {
619  ‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'] = ‪self::executePositionedStringInsertion(‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'], $addFields, $insertionPosition);
620  }
621 
639  protected static function ‪executePositionedStringInsertion($list, $insertionList, $insertionPosition = '')
640  {
641  $list = $newList = trim($list, ", \t\n\r\0\x0B");
642 
643  if ($insertionPosition !== '') {
644  [$location, $positionName] = ‪GeneralUtility::trimExplode(':', $insertionPosition, false, 2);
645  } else {
646  $location = '';
647  $positionName = '';
648  }
649 
650  if ($location !== 'replace') {
651  $insertionList = ‪self::removeDuplicatesForInsertion($insertionList, $list);
652  }
653 
654  if ($insertionList === '') {
655  return $list;
656  }
657  if ($list === '') {
658  return $insertionList;
659  }
660  if ($insertionPosition === '') {
661  return $list . ', ' . $insertionList;
662  }
663 
664  // The $insertPosition may be a palette: after:--palette--;;title
665  // In the $list the palette may contain a LLL string in between the ;;
666  // Adjust the regex to match that
667  $positionName = preg_quote($positionName, '/');
668  if (strpos($positionName, ';;') !== false) {
669  $positionName = str_replace(';;', ';[^;]*;', $positionName);
670  }
671 
672  $pattern = ('/(^|,\\s*)(' . $positionName . ')(;[^,$]+)?(,|$)/');
673  switch ($location) {
674  case 'after':
675  $newList = preg_replace($pattern, '$1$2$3, ' . $insertionList . '$4', $list);
676  break;
677  case 'before':
678  $newList = preg_replace($pattern, '$1' . $insertionList . ', $2$3$4', $list);
679  break;
680  case 'replace':
681  $newList = preg_replace($pattern, '$1' . $insertionList . '$4', $list);
682  break;
683  default:
684  }
685 
686  // When preg_replace did not replace anything; append the $insertionList.
687  if ($list === $newList) {
688  return $list . ', ' . $insertionList;
689  }
690  return $newList;
691  }
692 
708  protected static function ‪removeDuplicatesForInsertion($insertionList, $list = '')
709  {
710  $insertionListParts = preg_split('/\\s*,\\s*/', $insertionList);
711  $listMatches = [];
712  if ($list !== '') {
713  preg_match_all('/(?:^|,)\\s*\\b([^;,]+)\\b[^,]*/', $list, $listMatches);
714  $listMatches = $listMatches[1];
715  }
716 
717  $cleanInsertionListParts = [];
718  foreach ($insertionListParts as $fieldName) {
719  $fieldNameParts = explode(';', $fieldName, 2);
720  $cleanFieldName = $fieldNameParts[0];
721  if (
722  $cleanFieldName === '--linebreak--'
723  || (
724  !in_array($cleanFieldName, $cleanInsertionListParts, true)
725  && !in_array($cleanFieldName, $listMatches, true)
726  )
727  ) {
728  $cleanInsertionListParts[] = $fieldName;
729  }
730  }
731  return implode(', ', $cleanInsertionListParts);
732  }
733 
740  protected static function ‪explodeItemList($itemList)
741  {
742  $items = [];
743  $itemParts = ‪GeneralUtility::trimExplode(',', $itemList, true);
744  foreach ($itemParts as $itemPart) {
745  $itemDetails = ‪GeneralUtility::trimExplode(';', $itemPart, false, 5);
746  $key = $itemDetails[0];
747  if (strpos($key, '--') !== false) {
748  // If $key is a separator (--div--) or palette (--palette--) then it will be appended by a unique number. This must be removed again when using this value!
749  $key .= count($items);
750  }
751  if (!isset($items[$key])) {
752  $items[$key] = [
753  'rawData' => $itemPart,
754  'details' => []
755  ];
756  $details = [0 => 'field', 1 => 'label', 2 => 'palette'];
757  foreach ($details as $id => $property) {
758  $items[$key]['details'][$property] = $itemDetails[$id] ?? '';
759  }
760  }
761  }
762  return $items;
763  }
764 
773  protected static function ‪generateItemList(array $items, $useRawData = false)
774  {
775  $itemParts = [];
776  foreach ($items as $item => $itemDetails) {
777  if (strpos($item, '--') !== false) {
778  // If $item is a separator (--div--) or palette (--palette--) then it may have been appended by a unique number. This must be stripped away here.
779  $item = str_replace([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], '', $item);
780  }
781  if ($useRawData) {
782  $itemParts[] = $itemDetails['rawData'];
783  } else {
784  if (count($itemDetails['details']) > 1) {
785  $details = ['palette', 'label', 'field'];
786  $elements = [];
787  $addEmpty = false;
788  foreach ($details as $property) {
789  if ($itemDetails['details'][$property] !== '' || $addEmpty) {
790  $addEmpty = true;
791  array_unshift($elements, $itemDetails['details'][$property]);
792  }
793  }
794  $item = implode(';', $elements);
795  }
796  $itemParts[] = $item;
797  }
798  }
799  return implode(', ', $itemParts);
800  }
801 
809  public static function ‪allowTableOnStandardPages($table)
810  {
811  ‪$GLOBALS['PAGES_TYPES']['default']['allowedTables'] .= ',' . $table;
812  }
813 
824  public static function ‪addModule($main, $sub = '', $position = '', $path = null, $moduleConfiguration = [])
825  {
826  if (!isset(‪$GLOBALS['TBE_MODULES'])) {
827  ‪$GLOBALS['TBE_MODULES'] = [];
828  }
829  // If there is already a main module by this name:
830  // Adding the submodule to the correct position:
831  if (isset(‪$GLOBALS['TBE_MODULES'][$main]) && $sub) {
832  [$place, $modRef] = array_pad(‪GeneralUtility::trimExplode(':', $position, true), 2, null);
833  $modules = ',' . ‪$GLOBALS['TBE_MODULES'][$main] . ',';
834  if ($place === null || ($modRef !== null && !GeneralUtility::inList($modules, $modRef))) {
835  $place = 'bottom';
836  }
837  $modRef = ',' . $modRef . ',';
838  if (!GeneralUtility::inList($modules, $sub)) {
839  switch (strtolower($place)) {
840  case 'after':
841  $modules = str_replace($modRef, $modRef . $sub . ',', $modules);
842  break;
843  case 'before':
844  $modules = str_replace($modRef, ',' . $sub . $modRef, $modules);
845  break;
846  case 'top':
847  $modules = $sub . $modules;
848  break;
849  case 'bottom':
850  default:
851  $modules = $modules . $sub;
852  }
853  }
854  // Re-inserting the submodule list:
855  ‪$GLOBALS['TBE_MODULES'][$main] = trim($modules, ',');
856  } elseif (!isset(‪$GLOBALS['TBE_MODULES'][$main]) && empty($sub)) {
857  // Create a new main module, respecting the order, which is only possible when the module does not exist yet
858  $conf = ‪$GLOBALS['TBE_MODULES']['_configuration'] ?? [];
859  unset(‪$GLOBALS['TBE_MODULES']['_configuration']);
860  $navigationComponents = ‪$GLOBALS['TBE_MODULES']['_navigationComponents'] ?? [];
861  unset(‪$GLOBALS['TBE_MODULES']['_navigationComponents']);
862 
863  $modules = array_keys(‪$GLOBALS['TBE_MODULES']);
864  [$place, $moduleReference] = array_pad(‪GeneralUtility::trimExplode(':', $position, true), 2, null);
865  if ($place === null || ($moduleReference !== null && !in_array($moduleReference, $modules, true))) {
866  $place = 'bottom';
867  }
868  $newModules = [];
869  switch (strtolower($place)) {
870  case 'after':
871  foreach ($modules as $existingMainModule) {
872  $newModules[$existingMainModule] = ‪$GLOBALS['TBE_MODULES'][$existingMainModule];
873  if ($moduleReference === $existingMainModule) {
874  $newModules[$main] = '';
875  }
876  }
877  break;
878  case 'before':
879  foreach ($modules as $existingMainModule) {
880  if ($moduleReference === $existingMainModule) {
881  $newModules[$main] = '';
882  }
883  $newModules[$existingMainModule] = ‪$GLOBALS['TBE_MODULES'][$existingMainModule];
884  }
885  break;
886  case 'top':
887  $newModules[$main] = '';
888  $newModules += ‪$GLOBALS['TBE_MODULES'];
889  break;
890  case 'bottom':
891  default:
892  $newModules = ‪$GLOBALS['TBE_MODULES'];
893  $newModules[$main] = '';
894  }
895  ‪$GLOBALS['TBE_MODULES'] = $newModules;
896  ‪$GLOBALS['TBE_MODULES']['_configuration'] = $conf;
897  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'] = $navigationComponents;
898  } else {
899  // Create new main modules with only one submodule, $sub (or none if $sub is blank)
900  ‪$GLOBALS['TBE_MODULES'][$main] = $sub;
901  }
902 
903  // add additional configuration
904  $fullModuleSignature = $main . ($sub ? '_' . $sub : '');
905  if (is_array($moduleConfiguration) && !empty($moduleConfiguration)) {
906  // remove default icon if an icon identifier is available
907  if (!empty($moduleConfiguration['iconIdentifier'])
908  && !empty($moduleConfiguration['icon'])
909  && $moduleConfiguration['icon'] === 'EXT:extbase/Resources/Public/Icons/Extension.png'
910  ) {
911  unset($moduleConfiguration['icon']);
912  }
913  if (!empty($moduleConfiguration['icon'])) {
914  ‪$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
915  $iconIdentifier = 'module-' . $fullModuleSignature;
916  $iconProvider = ‪$iconRegistry->detectIconProvider($moduleConfiguration['icon']);
917  ‪$iconRegistry->registerIcon(
918  $iconIdentifier,
919  $iconProvider,
920  ['source' => GeneralUtility::getFileAbsFileName($moduleConfiguration['icon'])]
921  );
922  $moduleConfiguration['iconIdentifier'] = $iconIdentifier;
923  unset($moduleConfiguration['icon']);
924  }
925 
926  ‪$GLOBALS['TBE_MODULES']['_configuration'][$fullModuleSignature] = $moduleConfiguration;
927  }
928 
929  // Also register the module as regular route
930  $routeName = $moduleConfiguration['id'] ?? $fullModuleSignature;
931  // Build Route objects from the data
932  if (!empty($moduleConfiguration['path'])) {
933  $path = $moduleConfiguration['path'];
934  $path = '/' . ltrim($path, '/');
935  $legacyPath = '';
936  } else {
937  $path = str_replace('_', '/', $fullModuleSignature);
938  $path = trim($path, '/');
939  $legacyPath = '/' . $path . '/';
940  $path = '/module/' . $path;
941  }
942 
943  $options = [
944  'module' => true,
945  'moduleName' => $fullModuleSignature,
946  'access' => !empty($moduleConfiguration['access']) ? $moduleConfiguration['access'] : 'user,group'
947  ];
948  if (!empty($moduleConfiguration['routeTarget'])) {
949  $options['target'] = $moduleConfiguration['routeTarget'];
950  }
951 
952  $router = GeneralUtility::makeInstance(Router::class);
953  $router->addRoute($routeName, GeneralUtility::makeInstance(Route::class, $path, $options));
954  // bridge to allow to access old name like "/web/ts/" instead of "/module/web/ts/"
955  // @deprecated since TYPO3 v10.0, will be removed in TYPO3 v11.0.
956  if (!empty($legacyPath)) {
957  $router->addRoute('_legacyroutetomodule_' . $routeName, GeneralUtility::makeInstance(Route::class, $legacyPath, $options));
958  }
959  }
960 
973  public static function ‪insertModuleFunction($modname, $className, $_ = null, $title, $MM_key = 'function', $WS = '')
974  {
975  ‪$GLOBALS['TBE_MODULES_EXT'][$modname]['MOD_MENU'][$MM_key][$className] = [
976  'name' => $className,
977  'title' => $title,
978  'ws' => $WS
979  ];
980  }
981 
989  public static function ‪addPageTSConfig($content)
990  {
991  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultPageTSconfig'] .= '
992 [GLOBAL]
993 ' . $content;
994  }
995 
1003  public static function ‪addUserTSConfig($content)
1004  {
1005  ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['defaultUserTSconfig'] .= '
1006 [GLOBAL]
1007 ' . $content;
1008  }
1009 
1018  public static function ‪addLLrefForTCAdescr($key, $file)
1019  {
1020  if (empty($key)) {
1021  throw new \RuntimeException('No description key set in addLLrefForTCAdescr(). Provide it as first parameter', 1507321596);
1022  }
1023  if (!is_array(‪$GLOBALS['TCA_DESCR'][$key] ?? false)) {
1024  ‪$GLOBALS['TCA_DESCR'][$key] = [];
1025  }
1026  if (!is_array(‪$GLOBALS['TCA_DESCR'][$key]['refs'] ?? false)) {
1027  ‪$GLOBALS['TCA_DESCR'][$key]['refs'] = [];
1028  }
1029  ‪$GLOBALS['TCA_DESCR'][$key]['refs'][] = $file;
1030  }
1031 
1040  public static function ‪addNavigationComponent($module, $componentId, $extensionKey)
1041  {
1042  if (empty($extensionKey)) {
1043  throw new \RuntimeException('No extensionKey set in addNavigationComponent(). Provide it as third parameter', 1404068039);
1044  }
1045  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'][$module] = [
1046  'componentId' => $componentId,
1047  'extKey' => $extensionKey,
1048  'isCoreComponent' => false
1049  ];
1050  }
1051 
1058  public static function ‪addCoreNavigationComponent($module, $componentId)
1059  {
1060  ‪self::addNavigationComponent($module, $componentId, 'core');
1061  ‪$GLOBALS['TBE_MODULES']['_navigationComponents'][$module]['isCoreComponent'] = true;
1062  }
1063 
1064  /**************************************
1065  *
1066  * Adding SERVICES features
1067  *
1068  ***************************************/
1077  public static function ‪addService($extKey, $serviceType, $serviceKey, $info)
1078  {
1079  if (!$serviceType) {
1080  throw new \InvalidArgumentException('No serviceType given.', 1507321535);
1081  }
1082  if (!is_array($info)) {
1083  throw new \InvalidArgumentException('No information array given.', 1507321542);
1084  }
1085  $info['priority'] = max(0, min(100, $info['priority']));
1086  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
1087  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
1088  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
1089  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
1090  // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
1091  // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
1092  // even the activation is possible (a unix service might be possible on windows for some reasons)
1093  if (is_array(‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey] ?? false)) {
1094  // No check is done here - there might be configuration values only the service type knows about, so
1095  // we pass everything
1096  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], ‪$GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
1097  }
1098  // OS check
1099  // Empty $os means 'not limited to one OS', therefore a check is not needed
1100  if (‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] && ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] != '') {
1101  $os_type = ‪Environment::isWindows() ? 'WIN' : 'UNIX';
1102  $os = ‪GeneralUtility::trimExplode(',', strtoupper(‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
1103  if (!in_array($os_type, $os, true)) {
1104  ‪self::deactivateService($serviceType, $serviceKey);
1105  }
1106  }
1107  // Convert subtype list to array for quicker access
1108  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = [];
1109  $serviceSubTypes = ‪GeneralUtility::trimExplode(',', $info['subtype']);
1110  foreach ($serviceSubTypes as $subtype) {
1111  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
1112  }
1113  }
1114 
1123  public static function ‪findService($serviceType, $serviceSubType = '', $excludeServiceKeys = [])
1124  {
1125  $serviceKey = false;
1126  $serviceInfo = false;
1127  $priority = 0;
1128  $quality = 0;
1129  if (!is_array($excludeServiceKeys)) {
1130  trigger_error('ExtensionManagementUtility::findService() expects the third method argument to be an array instead of a comma-separated string. TYPO3 v11.0 will only support arrays as third argument for $excludeServiceKeys', E_USER_DEPRECATED);
1131  $excludeServiceKeys = ‪GeneralUtility::trimExplode(',', $excludeServiceKeys, true);
1132  }
1133  if (is_array(‪$GLOBALS['T3_SERVICES'][$serviceType])) {
1134  foreach (‪$GLOBALS['T3_SERVICES'][$serviceType] as $key => $info) {
1135  if (in_array($key, $excludeServiceKeys)) {
1136  continue;
1137  }
1138  // Select a subtype randomly
1139  // Useful to start a service by service key without knowing his subtypes - for testing purposes
1140  if ($serviceSubType === '*') {
1141  $serviceSubType = key($info['serviceSubTypes']);
1142  }
1143  // This matches empty subtype too
1144  if ($info['available'] && ($info['subtype'] == $serviceSubType || $info['serviceSubTypes'][$serviceSubType]) && $info['priority'] >= $priority) {
1145  // Has a lower quality than the already found, therefore we skip this service
1146  if ($info['priority'] == $priority && $info['quality'] < $quality) {
1147  continue;
1148  }
1149  // Check if the service is available
1150  $info['available'] = ‪self::isServiceAvailable($serviceType, $key, $info);
1151  // Still available after exec check?
1152  if ($info['available']) {
1153  $serviceKey = $key;
1154  $priority = $info['priority'];
1155  $quality = $info['quality'];
1156  }
1157  }
1158  }
1159  }
1160  if ($serviceKey) {
1161  $serviceInfo = ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey];
1162  }
1163  return $serviceInfo;
1164  }
1165 
1174  public static function ‪findServiceByKey($serviceKey)
1175  {
1176  if (is_array(‪$GLOBALS['T3_SERVICES'])) {
1177  // Loop on all service types
1178  // NOTE: we don't care about the actual type, we are looking for a specific key
1179  foreach (‪$GLOBALS['T3_SERVICES'] as $serviceType => $servicesPerType) {
1180  if (isset($servicesPerType[$serviceKey])) {
1181  $serviceDetails = $servicesPerType[$serviceKey];
1182  // Test if service is available
1183  if (self::isServiceAvailable($serviceType, $serviceKey, $serviceDetails)) {
1184  // We have found the right service, return its information
1185  return $serviceDetails;
1186  }
1187  }
1188  }
1189  }
1190  throw new \TYPO3\CMS\Core\Exception('Service not found for key: ' . $serviceKey, 1319217244);
1191  }
1192 
1201  public static function ‪isServiceAvailable($serviceType, $serviceKey, $serviceDetails)
1202  {
1203  // If the service depends on external programs - check if they exists
1204  if (trim($serviceDetails['exec'])) {
1205  $executables = ‪GeneralUtility::trimExplode(',', $serviceDetails['exec'], true);
1206  foreach ($executables as $executable) {
1207  // If at least one executable file is not available, exit early returning FALSE
1208  if (!‪CommandUtility::checkCommand($executable)) {
1209  ‪self::deactivateService($serviceType, $serviceKey);
1210  return false;
1211  }
1212  }
1213  }
1214  // The service is available
1215  return true;
1216  }
1217 
1224  public static function ‪deactivateService($serviceType, $serviceKey)
1225  {
1226  // ... maybe it's better to move non-available services to a different array??
1227  ‪$GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] = false;
1228  }
1229 
1230  /**************************************
1231  *
1232  * Adding FRONTEND features
1233  *
1234  ***************************************/
1248  public static function ‪addPlugin($itemArray, $type = 'list_type', $extensionKey = null)
1249  {
1250  if (!isset($extensionKey)) {
1251  throw new \InvalidArgumentException(
1252  'No extension key could be determined when calling addPlugin()!'
1253  . LF
1254  . 'This method is meant to be called from Configuration/TCA/Overrides files. '
1255  . 'The extension key needs to be specified as third parameter. '
1256  . 'Calling it from any other place e.g. ext_localconf.php does not work and is not supported.',
1257  1404068038
1258  );
1259  }
1260  if (!isset($itemArray[2]) || !$itemArray[2]) {
1261  // @todo do we really set $itemArray[2], even if we cannot find an icon? (as that means it's set to 'EXT:foobar/')
1262  $itemArray[2] = 'EXT:' . $extensionKey . '/' . static::getExtensionIcon(static::$packageManager->getPackage($extensionKey)->getPackagePath());
1263  }
1264  if (!isset($itemArray[3])) {
1265  $itemArray[3] = 'default';
1266  }
1267  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'])) {
1268  foreach (‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'] as $k => $v) {
1269  if ((string)$v[1] === (string)$itemArray[1]) {
1270  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][$k] = $itemArray;
1271  return;
1272  }
1273  }
1274  ‪$GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][] = $itemArray;
1275  }
1276  }
1277 
1288  public static function ‪addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch = 'list')
1289  {
1290  if (is_array(‪$GLOBALS['TCA']['tt_content']['columns']) && is_array(‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'])) {
1291  ‪$GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'][$piKeyToMatch . ',' . $CTypeToMatch] = $value;
1292  }
1293  }
1294 
1304  public static function ‪addToInsertRecords($table, $content_table = 'tt_content', $content_field = 'records')
1305  {
1306  if (is_array(‪$GLOBALS['TCA'][$content_table]['columns']) && isset(‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'])) {
1307  ‪$GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'] .= ',' . $table;
1308  }
1309  }
1310 
1336  public static function ‪addPItoST43($key, $_ = '', $suffix = '', $type = 'list_type', $cacheable = false)
1337  {
1338  $cN = ‪self::getCN($key);
1339  // General plugin
1340  $pluginContent = trim('
1341 plugin.' . $cN . $suffix . ' = USER' . ($cacheable ? '' : '_INT') . '
1342 plugin.' . $cN . $suffix . '.userFunc = ' . $cN . $suffix . '->main
1343 ');
1344  ‪self::addTypoScript($key, 'setup', '
1345 # Setting ' . $key . ' plugin TypoScript
1346 ' . $pluginContent);
1347  // Add after defaultContentRendering
1348  switch ($type) {
1349  case 'list_type':
1350  $addLine = 'tt_content.list.20.' . $key . $suffix . ' = < plugin.' . $cN . $suffix;
1351  break;
1352  case 'CType':
1353  $addLine = trim('
1354 tt_content.' . $key . $suffix . ' =< lib.contentElement
1355 tt_content.' . $key . $suffix . ' {
1356  templateName = Generic
1357  20 =< plugin.' . $cN . $suffix . '
1358 }
1359 ');
1360  break;
1361  case 'header_layout':
1362  $addLine = 'lib.stdheader.10.' . $key . $suffix . ' = < plugin.' . $cN . $suffix;
1363  break;
1364  case 'includeLib':
1365  $addLine = 'page.1000 = < plugin.' . $cN . $suffix;
1366  break;
1367  default:
1368  $addLine = '';
1369  }
1370  if ($addLine) {
1371  ‪self::addTypoScript($key, 'setup', '
1372 # Setting ' . $key . ' plugin TypoScript
1373 ' . $addLine . '
1374 ', 'defaultContentRendering');
1375  }
1376  }
1377 
1388  public static function ‪addStaticFile($extKey, $path, $title)
1389  {
1390  if (!$extKey) {
1391  throw new \InvalidArgumentException('No extension key given.', 1507321291);
1392  }
1393  if (!$path) {
1394  throw new \InvalidArgumentException('No file path given.', 1507321297);
1395  }
1396  if (is_array(‪$GLOBALS['TCA']['sys_template']['columns'])) {
1397  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $path);
1398  $itemArray = [trim($title . ' (' . $extKey . ')'), $value];
1399  ‪$GLOBALS['TCA']['sys_template']['columns']['include_static_file']['config']['items'][] = $itemArray;
1400  }
1401  }
1402 
1412  public static function ‪registerPageTSConfigFile($extKey, $filePath, $title)
1413  {
1414  if (!$extKey) {
1415  throw new \InvalidArgumentException('No extension key given.', 1447789490);
1416  }
1417  if (!$filePath) {
1418  throw new \InvalidArgumentException('No file path given.', 1447789491);
1419  }
1420  if (!isset(‪$GLOBALS['TCA']['pages']['columns']) || !is_array(‪$GLOBALS['TCA']['pages']['columns'])) {
1421  throw new \InvalidArgumentException('No TCA definition for table "pages".', 1447789492);
1422  }
1423 
1424  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $filePath);
1425  $itemArray = [trim($title . ' (' . $extKey . ')'), $value];
1426  ‪$GLOBALS['TCA']['pages']['columns']['tsconfig_includes']['config']['items'][] = $itemArray;
1427  }
1428 
1436  public static function ‪addTypoScriptSetup($content)
1437  {
1438  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup'] .= '
1439 [GLOBAL]
1440 ' . $content;
1441  }
1442 
1450  public static function ‪addTypoScriptConstants($content)
1451  {
1452  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_constants'] .= '
1453 [GLOBAL]
1454 ' . $content;
1455  }
1456 
1474  public static function ‪addTypoScript(string $key, string $type, string $content, $afterStaticUid = 0)
1475  {
1476  if ($type !== 'setup' && $type !== 'constants') {
1477  throw new \InvalidArgumentException('Argument $type must be set to either "setup" or "constants" when calling addTypoScript from extension "' . $key . '"', 1507321200);
1478  }
1479  $content = '
1480 
1481 [GLOBAL]
1482 #############################################
1483 ## TypoScript added by extension "' . $key . '"
1484 #############################################
1485 
1486 ' . $content;
1487  if ($afterStaticUid) {
1488  // If 'content (default)' is targeted (static uid 43),
1489  // 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
1490  if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
1491  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'])) {
1492  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] = '';
1493  }
1494  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
1495  } else {
1496  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid])) {
1497  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] = '';
1498  }
1499  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
1500  }
1501  } else {
1502  if (!isset(‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type])) {
1503  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] = '';
1504  }
1505  ‪$GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
1506  }
1507  }
1508 
1509  /***************************************
1510  *
1511  * Internal extension management methods
1512  *
1513  ***************************************/
1522  public static function ‪getExtensionIcon($extensionPath, $returnFullPath = false)
1523  {
1524  $icon = '';
1525  $locationsToCheckFor = [
1526  'Resources/Public/Icons/Extension.svg',
1527  'Resources/Public/Icons/Extension.png',
1528  'Resources/Public/Icons/Extension.gif',
1529  'ext_icon.svg',
1530  'ext_icon.png',
1531  'ext_icon.gif',
1532  ];
1533  foreach ($locationsToCheckFor as $fileLocation) {
1534  if (file_exists($extensionPath . $fileLocation)) {
1535  $icon = $fileLocation;
1536  break;
1537  }
1538  }
1539  return $returnFullPath ? $extensionPath . $icon : $icon;
1540  }
1541 
1554  public static function ‪loadExtLocalconf($allowCaching = true, FrontendInterface $codeCache = null)
1555  {
1556  if ($allowCaching) {
1557  $codeCache = $codeCache ?? ‪self::getCacheManager()->‪getCache('core');
1558  $cacheIdentifier = ‪self::getExtLocalconfCacheIdentifier();
1559  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1560  if (!$hasCache) {
1563  }
1564  } else {
1566  }
1567  }
1572  protected static function ‪loadSingleExtLocalconfFiles()
1573  {
1574  foreach (static::$packageManager->getActivePackages() as $package) {
1575  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1576  if (@file_exists($extLocalconfPath)) {
1577  require $extLocalconfPath;
1578  }
1579  }
1580  }
1581 
1587  protected static function ‪createExtLocalconfCacheEntry(‪FrontendInterface $codeCache)
1588  {
1589  $phpCodeToCache = [];
1590  // Set same globals as in loadSingleExtLocalconfFiles()
1591  $phpCodeToCache[] = '';
1594  $phpCodeToCache[] = '';
1595  // Iterate through loaded extensions and add ext_localconf content
1596  foreach (static::$packageManager->getActivePackages() as $package) {
1597  $extensionKey = $package->getPackageKey();
1598  $extLocalconfPath = $package->getPackagePath() . 'ext_localconf.php';
1599  if (@file_exists($extLocalconfPath)) {
1600  // Include a header per extension to make the cache file more readable
1601  $phpCodeToCache[] = '';
1605  $phpCodeToCache[] = '';
1606  // Add ext_localconf.php content of extension
1607  $phpCodeToCache[] = trim((string)file_get_contents($extLocalconfPath));
1608  $phpCodeToCache[] = '';
1609  $phpCodeToCache[] = '';
1610  }
1611  }
1612  $phpCodeToCache = implode(LF, $phpCodeToCache);
1613  // Remove all start and ending php tags from content
1614  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1615  $codeCache->‪set(self::getExtLocalconfCacheIdentifier(), $phpCodeToCache);
1616  }
1617 
1623  protected static function ‪getExtLocalconfCacheIdentifier()
1624  {
1625  return 'ext_localconf_' . sha1((string)(new Typo3Version()) . ‪Environment::getProjectPath() . 'extLocalconf' . serialize(‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1626  }
1627 
1641  public static function ‪loadBaseTca($allowCaching = true, FrontendInterface $codeCache = null)
1642  {
1643  if ($allowCaching) {
1644  $codeCache = $codeCache ?? ‪self::getCacheManager()->‪getCache('core');
1645  $cacheIdentifier = static::getBaseTcaCacheIdentifier();
1646  $cacheData = $codeCache->require($cacheIdentifier);
1647  if ($cacheData) {
1648  ‪$GLOBALS['TCA'] = $cacheData['tca'];
1649  GeneralUtility::setSingletonInstance(
1650  CategoryRegistry::class,
1651  unserialize(
1652  $cacheData['categoryRegistry'],
1653  ['allowed_classes' => [CategoryRegistry::class]]
1654  )
1655  );
1656  } else {
1657  static::buildBaseTcaFromSingleFiles();
1658  static::createBaseTcaCacheFile($codeCache);
1659  }
1660  } else {
1661  static::buildBaseTcaFromSingleFiles();
1662  }
1663  }
1664 
1672  protected static function ‪buildBaseTcaFromSingleFiles()
1673  {
1674  ‪$GLOBALS['TCA'] = [];
1675 
1676  $activePackages = static::$packageManager->getActivePackages();
1677 
1678  // First load "full table" files from Configuration/TCA
1679  foreach ($activePackages as $package) {
1680  try {
1681  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA');
1682  } catch (\InvalidArgumentException $e) {
1683  // No such directory in this package
1684  continue;
1685  }
1686  foreach (‪$finder as $fileInfo) {
1687  $tcaOfTable = require $fileInfo->getPathname();
1688  if (is_array($tcaOfTable)) {
1689  $tcaTableName = substr($fileInfo->getBasename(), 0, -4);
1690  ‪$GLOBALS['TCA'][$tcaTableName] = $tcaOfTable;
1691  }
1692  }
1693  }
1694 
1695  // Apply category stuff
1697 
1698  // Execute override files from Configuration/TCA/Overrides
1699  foreach ($activePackages as $package) {
1700  try {
1701  ‪$finder = Finder::create()->files()->sortByName()->depth(0)->name('*.php')->in($package->getPackagePath() . 'Configuration/TCA/Overrides');
1702  } catch (\InvalidArgumentException $e) {
1703  // No such directory in this package
1704  continue;
1705  }
1706  foreach (‪$finder as $fileInfo) {
1707  require $fileInfo->getPathname();
1708  }
1709  }
1710 
1711  // Call the TcaMigration and log any deprecations.
1712  $tcaMigration = GeneralUtility::makeInstance(TcaMigration::class);
1713  ‪$GLOBALS['TCA'] = $tcaMigration->migrate(‪$GLOBALS['TCA']);
1714  $messages = $tcaMigration->getMessages();
1715  if (!empty($messages)) {
1716  $context = 'Automatic TCA migration done during bootstrap. Please adapt TCA accordingly, these migrations'
1717  . ' will be removed. The backend module "Configuration -> TCA" shows the modified values.'
1718  . ' Please adapt these areas:';
1719  array_unshift($messages, $context);
1720  trigger_error(implode(LF, $messages), E_USER_DEPRECATED);
1721  }
1722 
1723  // TCA preparation
1724  $tcaPreparation = GeneralUtility::makeInstance(TcaPreparation::class);
1725  ‪$GLOBALS['TCA'] = $tcaPreparation->prepare(‪$GLOBALS['TCA']);
1726 
1727  static::dispatchTcaIsBeingBuiltEvent(‪$GLOBALS['TCA']);
1728  }
1729 
1735  protected static function ‪dispatchTcaIsBeingBuiltEvent(array ‪$tca)
1736  {
1737  ‪$GLOBALS['TCA'] = static::$eventDispatcher->dispatch(new AfterTcaCompilationEvent(‪$tca))->getTca();
1738  }
1739 
1746  protected static function ‪createBaseTcaCacheFile(FrontendInterface $codeCache)
1747  {
1748  $codeCache->set(
1749  static::getBaseTcaCacheIdentifier(),
1750  'return '
1751  . var_export(['tca' => ‪$GLOBALS['TCA'], 'categoryRegistry' => serialize(‪CategoryRegistry::getInstance())], true)
1752  . ';'
1753  );
1754  }
1755 
1761  protected static function ‪getBaseTcaCacheIdentifier()
1762  {
1763  return 'tca_base_' . sha1((string)(new Typo3Version()) . ‪Environment::getProjectPath() . 'tca_code' . serialize(‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1764  }
1765 
1777  public static function ‪loadExtTables($allowCaching = true)
1778  {
1779  if ($allowCaching && !self::$extTablesWasReadFromCacheOnce) {
1780  self::$extTablesWasReadFromCacheOnce = true;
1781  $cacheIdentifier = ‪self::getExtTablesCacheIdentifier();
1783  $codeCache = ‪self::getCacheManager()->‪getCache('core');
1784  $hasCache = $codeCache->require($cacheIdentifier) !== false;
1785  if (!$hasCache) {
1788  }
1789  } else {
1791  }
1792  }
1797  protected static function ‪loadSingleExtTablesFiles()
1798  {
1799  // Load each ext_tables.php file of loaded extensions
1800  foreach (static::$packageManager->getActivePackages() as $package) {
1801  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1802  if (@file_exists($extTablesPath)) {
1803  require $extTablesPath;
1804  }
1805  }
1806  }
1811  protected static function ‪createExtTablesCacheEntry()
1812  {
1813  $phpCodeToCache = [];
1814  // Set same globals as in loadSingleExtTablesFiles()
1815  $phpCodeToCache[] = '';
1818  $phpCodeToCache[] = '';
1819  // Iterate through loaded extensions and add ext_tables content
1820  foreach (static::$packageManager->getActivePackages() as $package) {
1821  $extensionKey = $package->getPackageKey();
1822  $extTablesPath = $package->getPackagePath() . 'ext_tables.php';
1823  if (@file_exists($extTablesPath)) {
1824  // Include a header per extension to make the cache file more readable
1825  $phpCodeToCache[] = '';
1829  $phpCodeToCache[] = '';
1830  // Add ext_tables.php content of extension
1831  $phpCodeToCache[] = trim((string)file_get_contents($extTablesPath));
1832  $phpCodeToCache[] = '';
1833  }
1834  }
1835  $phpCodeToCache = implode(LF, $phpCodeToCache);
1836  // Remove all start and ending php tags from content
1837  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1838  ‪self::getCacheManager()->‪getCache('core')->‪set(self::getExtTablesCacheIdentifier(), $phpCodeToCache);
1839  }
1840 
1846  protected static function ‪getExtTablesCacheIdentifier()
1847  {
1848  return 'ext_tables_' . sha1((string)(new ‪Typo3Version()) . ‪Environment::getProjectPath() . 'extTables' . serialize(‪$GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1849  }
1850 
1856  public static function ‪getLoadedExtensionListArray()
1857  {
1858  return array_keys(static::$packageManager->getActivePackages());
1859  }
1860 
1870  public static function ‪loadExtension($extensionKey)
1871  {
1872  if (static::$packageManager->isPackageActive($extensionKey)) {
1873  throw new \RuntimeException('Extension already loaded', 1342345486);
1874  }
1875  static::$packageManager->activatePackage($extensionKey);
1876  }
1877 
1887  public static function ‪unloadExtension($extensionKey)
1888  {
1889  if (!static::$packageManager->isPackageActive($extensionKey)) {
1890  throw new \RuntimeException('Extension not loaded', 1342345487);
1891  }
1892  static::$packageManager->deactivatePackage($extensionKey);
1893  }
1894 
1907  public static function ‪makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = [], $override = false)
1908  {
1909  // Update the category registry
1910  $result = ‪CategoryRegistry::getInstance()->‪add($extensionKey, $tableName, $fieldName, $options, $override);
1911  if ($result === false) {
1912  GeneralUtility::makeInstance(LogManager::class)
1913  ->getLogger(__CLASS__)
1914  ->warning(sprintf(
1915  CategoryRegistry::class . ': no category registered for table "%s". Key was already registered.',
1916  $tableName
1917  ));
1918  }
1919  }
1920 }
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\dispatchTcaIsBeingBuiltEvent
‪static dispatchTcaIsBeingBuiltEvent(array $tca)
Definition: ExtensionManagementUtility.php:1731
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptConstants
‪static addTypoScriptConstants($content)
Definition: ExtensionManagementUtility.php:1446
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addModule
‪static addModule($main, $sub='', $position='', $path=null, $moduleConfiguration=[])
Definition: ExtensionManagementUtility.php:820
‪$iconRegistry
‪$iconRegistry
Definition: ext_localconf.php:43
‪TYPO3\CMS\Core\Migrations\TcaMigration
Definition: TcaMigration.php:26
‪TYPO3\CMS\Core\Cache\CacheManager\getCache
‪FrontendInterface getCache($identifier)
Definition: CacheManager.php:141
‪$finder
‪if(PHP_SAPI !=='cli') $finder
Definition: header-comment.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtTablesCacheIdentifier
‪static string getExtTablesCacheIdentifier()
Definition: ExtensionManagementUtility.php:1842
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\unloadExtension
‪static unloadExtension($extensionKey)
Definition: ExtensionManagementUtility.php:1883
‪TYPO3\CMS\Core\Utility\CommandUtility\checkCommand
‪static bool checkCommand($cmd, $handler='')
Definition: CommandUtility.php:160
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTypoScriptSetup
‪static addTypoScriptSetup($content)
Definition: ExtensionManagementUtility.php:1432
‪TYPO3\CMS\Core\Information\Typo3Version
Definition: Typo3Version.php:21
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getFileFieldTCAConfig
‪static array getFileFieldTCAConfig($fieldName, array $customSettingOverride=[], $allowedFileExtensions='', $disallowedFileExtensions='')
Definition: ExtensionManagementUtility.php:550
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\allowTableOnStandardPages
‪static allowTableOnStandardPages($table)
Definition: ExtensionManagementUtility.php:805
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\insertModuleFunction
‪static insertModuleFunction($modname, $className, $_=null, $title, $MM_key='function', $WS='')
Definition: ExtensionManagementUtility.php:969
‪TYPO3\CMS\Core\Configuration\Event\AfterTcaCompilationEvent
Definition: AfterTcaCompilationEvent.php:27
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtLocalconfCacheEntry
‪static createExtLocalconfCacheEntry(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1583
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtension
‪static loadExtension($extensionKey)
Definition: ExtensionManagementUtility.php:1866
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$eventDispatcher
‪static EventDispatcherInterface $eventDispatcher
Definition: ExtensionManagementUtility.php:73
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtLocalconfFiles
‪static loadSingleExtLocalconfFiles()
Definition: ExtensionManagementUtility.php:1568
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToPalette
‪static addFieldsToPalette($table, $palette, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:390
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTcaSelectItem
‪static addTcaSelectItem($table, $field, array $item, $relativeToField='', $relativePosition='')
Definition: ExtensionManagementUtility.php:431
‪TYPO3\CMS\Core\Core\Environment\isWindows
‪static bool isWindows()
Definition: Environment.php:292
‪TYPO3\CMS\Core\Utility
Definition: ArrayUtility.php:16
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findService
‪static mixed findService($serviceType, $serviceSubType='', $excludeServiceKeys=[])
Definition: ExtensionManagementUtility.php:1119
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getBaseTcaCacheIdentifier
‪static string getBaseTcaCacheIdentifier()
Definition: ExtensionManagementUtility.php:1757
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPlugin
‪static addPlugin($itemArray, $type='list_type', $extensionKey=null)
Definition: ExtensionManagementUtility.php:1244
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToAllTCAtypes
‪static addToAllTCAtypes($table, $newFieldsString, $typeList='', $position='')
Definition: ExtensionManagementUtility.php:209
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addTCAcolumns
‪static addTCAcolumns($table, $columnArray)
Definition: ExtensionManagementUtility.php:188
‪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:490
‪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:1332
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createExtTablesCacheEntry
‪static createExtTablesCacheEntry()
Definition: ExtensionManagementUtility.php:1807
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isServiceAvailable
‪static bool isServiceAvailable($serviceType, $serviceKey, $serviceDetails)
Definition: ExtensionManagementUtility.php:1197
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToAllPalettesOfField
‪static addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:337
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPiFlexFormValue
‪static addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch='list')
Definition: ExtensionManagementUtility.php:1284
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\makeCategorizable
‪static makeCategorizable($extensionKey, $tableName, $fieldName='categories', array $options=[], $override=false)
Definition: ExtensionManagementUtility.php:1903
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\generateItemList
‪static string generateItemList(array $items, $useRawData=false)
Definition: ExtensionManagementUtility.php:769
‪TYPO3\CMS\Core\Category\CategoryRegistry\getInstance
‪static CategoryRegistry getInstance()
Definition: CategoryRegistry.php:52
‪TYPO3\CMS\Core\Core\Environment\getProjectPath
‪static string getProjectPath()
Definition: Environment.php:169
‪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:1220
‪TYPO3\CMS\Core\Category\CategoryRegistry
Definition: CategoryRegistry.php:29
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\explodeItemList
‪static array explodeItemList($itemList)
Definition: ExtensionManagementUtility.php:736
‪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:157
‪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:999
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addStaticFile
‪static addStaticFile($extKey, $path, $title)
Definition: ExtensionManagementUtility.php:1384
‪TYPO3\CMS\Core\Preparations\TcaPreparation
Definition: TcaPreparation.php:30
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addLLrefForTCAdescr
‪static addLLrefForTCAdescr($key, $file)
Definition: ExtensionManagementUtility.php:1014
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\executePositionedStringInsertion
‪static string executePositionedStringInsertion($list, $insertionList, $insertionPosition='')
Definition: ExtensionManagementUtility.php:635
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadSingleExtTablesFiles
‪static loadSingleExtTablesFiles()
Definition: ExtensionManagementUtility.php:1793
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:38
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter
Definition: FileExtensionFilter.php:28
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getCN
‪static string getCN($key)
Definition: ExtensionManagementUtility.php:142
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\$packageManager
‪static PackageManager $packageManager
Definition: ExtensionManagementUtility.php:57
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\registerPageTSConfigFile
‪static registerPageTSConfigFile($extKey, $filePath, $title)
Definition: ExtensionManagementUtility.php:1408
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\findServiceByKey
‪static array findServiceByKey($serviceKey)
Definition: ExtensionManagementUtility.php:1170
‪TYPO3\CMS\Core\Category\CategoryRegistry\add
‪bool add($extensionKey, $tableName, $fieldName='categories', array $options=[], $override=false)
Definition: CategoryRegistry.php:85
‪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:1470
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:30
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addPageTSConfig
‪static addPageTSConfig($content)
Definition: ExtensionManagementUtility.php:985
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtTables
‪static loadExtTables($allowCaching=true)
Definition: ExtensionManagementUtility.php:1773
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addFieldsToUserSettings
‪static addFieldsToUserSettings($addFields, $insertionPosition='')
Definition: ExtensionManagementUtility.php:613
‪$tca
‪$tca
Definition: sys_file_metadata.php:5
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\createBaseTcaCacheFile
‪static createBaseTcaCacheFile(FrontendInterface $codeCache)
Definition: ExtensionManagementUtility.php:1742
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\extPath
‪static string extPath($key, $script='')
Definition: ExtensionManagementUtility.php:127
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadBaseTca
‪static loadBaseTca($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1637
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getLoadedExtensionListArray
‪static array getLoadedExtensionListArray()
Definition: ExtensionManagementUtility.php:1852
‪TYPO3\CMS\Core\Package\Exception
Definition: InvalidPackageKeyException.php:16
‪TYPO3\CMS\Core\Category\CategoryRegistry\applyTcaForPreRegisteredTables
‪applyTcaForPreRegisteredTables()
Definition: CategoryRegistry.php:215
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\getExtLocalconfCacheIdentifier
‪static string getExtLocalconfCacheIdentifier()
Definition: ExtensionManagementUtility.php:1619
‪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:1518
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addNavigationComponent
‪static addNavigationComponent($module, $componentId, $extensionKey)
Definition: ExtensionManagementUtility.php:1036
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\loadExtLocalconf
‪static loadExtLocalconf($allowCaching=true, FrontendInterface $codeCache=null)
Definition: ExtensionManagementUtility.php:1550
‪TYPO3\CMS\Backend\Routing\Router
Definition: Router.php:34
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addToInsertRecords
‪static addToInsertRecords($table, $content_table='tt_content', $content_field='records')
Definition: ExtensionManagementUtility.php:1300
‪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:704
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\addService
‪static addService($extKey, $serviceType, $serviceKey, $info)
Definition: ExtensionManagementUtility.php:1073
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\buildBaseTcaFromSingleFiles
‪static buildBaseTcaFromSingleFiles()
Definition: ExtensionManagementUtility.php:1668
‪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:1054