TYPO3 CMS  TYPO3_6-2
ExtensionManagementUtility.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3 
26 
27  static protected $extensionKeyMap;
28 
39  static protected $extTablesWasReadFromCacheOnce = FALSE;
40 
44  static protected $packageManager;
45 
53  static public function setPackageManager(\TYPO3\CMS\Core\Package\PackageManager $packageManager) {
54  static::$packageManager = $packageManager;
55  }
56 
60  static protected $cacheManager;
61 
67  static protected function getCacheManager() {
68  if (static::$cacheManager === NULL) {
69  static::$cacheManager = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\CacheManager');
70  }
71  return static::$cacheManager;
72  }
73 
77  static protected $signalSlotDispatcher;
78 
84  static protected function getSignalSlotDispatcher() {
85  if (static::$signalSlotDispatcher === NULL) {
86  static::$signalSlotDispatcher = GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
87  }
89  }
90 
91  /**************************************
92  *
93  * PATHS and other evaluation
94  *
95  ***************************************/
104  static public function isLoaded($key, $exitOnError = FALSE) {
105  $isLoaded = static::$packageManager->isPackageActive($key);
106  if ($exitOnError && !$isLoaded) {
107  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension "' . $key . '" is not loaded!', 1270853910);
108  }
109  return $isLoaded;
110  }
111 
120  static public function extPath($key, $script = '') {
121  if (!static::$packageManager->isPackageActive($key)) {
122  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension key "' . $key . '" is NOT loaded!', 1365429656);
123  }
124  return static::$packageManager->getPackage($key)->getPackagePath() . $script;
125  }
126 
137  static public function extRelPath($key) {
138  if (!static::$packageManager->isPackageActive($key)) {
139  throw new \BadFunctionCallException('TYPO3 Fatal Error: Extension key "' . $key . '" is NOT loaded!', 1365429673);
140  }
141  $relativePathToSiteRoot = self::siteRelPath($key);
142  if (substr($relativePathToSiteRoot, 0, $typo3MainDirLength = strlen(TYPO3_mainDir)) === TYPO3_mainDir) {
143  $relativePathToSiteRoot = substr($relativePathToSiteRoot, $typo3MainDirLength);
144  } else {
145  $relativePathToSiteRoot = '../' . $relativePathToSiteRoot;
146  }
147  return $relativePathToSiteRoot;
148  }
149 
158  static public function siteRelPath($key) {
159  return \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix(self::extPath($key));
160  }
161 
169  static public function getCN($key) {
170  return strpos($key, 'user_') === 0 ? 'user_' . str_replace('_', '', substr($key, 5)) : 'tx_' . str_replace('_', '', $key);
171  }
172 
179  static public function getExtensionKeyByPrefix($prefix) {
180  $result = FALSE;
181  // Build map of short keys referencing to real keys:
182  if (!isset(self::$extensionKeyMap)) {
183  self::$extensionKeyMap = array();
184  foreach (static::$packageManager->getActivePackages() as $package) {
185  $shortKey = str_replace('_', '', $package->getPackageKey());
186  self::$extensionKeyMap[$shortKey] = $package->getPackageKey();
187  }
188  }
189  // Lookup by the given short key:
190  $parts = explode('_', $prefix);
191  if (isset(self::$extensionKeyMap[$parts[1]])) {
192  $result = self::$extensionKeyMap[$parts[1]];
193  }
194  return $result;
195  }
196 
202  static public function clearExtensionKeyMap() {
203  self::$extensionKeyMap = NULL;
204  }
205 
216  static public function getExtensionVersion($key) {
217  if (!is_string($key) || empty($key)) {
218  throw new \InvalidArgumentException('Extension key must be a non-empty string.', 1294586096);
219  }
220  if (!static::isLoaded($key)) {
221  return '';
222  }
223  $version = static::$packageManager->getPackage($key)->getPackageMetaData()->getVersion();
224  if (empty($version)) {
225  throw new \TYPO3\CMS\Core\Package\Exception('Version number in composer manifest of package "' . $key . '" is missing or invalid', 1395614959);
226  }
227  return $version;
228  }
229 
230  /**************************************
231  *
232  * Adding BACKEND features
233  * (related to core features)
234  *
235  ***************************************/
248  static public function addTCAcolumns($table, $columnArray, $addTofeInterface = FALSE) {
249  if (is_array($columnArray) && is_array($GLOBALS['TCA'][$table]) && is_array($GLOBALS['TCA'][$table]['columns'])) {
250  // Candidate for array_merge() if integer-keys will some day make trouble...
251  $GLOBALS['TCA'][$table]['columns'] = array_merge($GLOBALS['TCA'][$table]['columns'], $columnArray);
252  if ($addTofeInterface) {
254  'Usage of feInterface is no longer part of the TYPO3 CMS Core. Please check EXT:' . $GLOBALS['_EXTKEY'] . '.'
255  );
256  }
257  }
258  }
259 
274  static public function addToAllTCAtypes($table, $newFieldsString, $typeList = '', $position = '') {
275  $newFieldsString = trim($newFieldsString);
276  if ($newFieldsString === '' || !is_array($GLOBALS['TCA'][$table]['types'])) {
277  return;
278  }
279  list($positionIdentifier, $entityName) = GeneralUtility::trimExplode(':', $position);
280  $palettesChanged = array();
281 
282  foreach ($GLOBALS['TCA'][$table]['types'] as $type => &$typeDetails) {
283  // skip if we don't want to add the field for this type
284  if ($typeList !== '' && !GeneralUtility::inList($typeList, $type)) {
285  continue;
286  }
287  // skip if fields were already added
288  if (!isset($typeDetails['showitem'])) {
289  continue;
290  }
291 
292  $fieldArray = GeneralUtility::trimExplode(',', $typeDetails['showitem'], TRUE);
293  if (in_array($newFieldsString, $fieldArray, TRUE)) {
294  continue;
295  }
296 
297  $fieldExists = FALSE;
298  $newPosition = '';
299  if (is_array($GLOBALS['TCA'][$table]['palettes'])) {
300  // Get the palette names used in current showitem
301  $paletteCount = preg_match_all('/(?:^|,) # Line start or a comma
302  (?:
303  \\s*\\-\\-palette\\-\\-;[^;]*;([^,$]*)| # --palette--;label;paletteName
304  \\s*\\b[^;,]+\\b(?:;[^;]*;([^;,]+);?[^;,]*;?)?[^,]* # field;label;paletteName[;options[;colors]]
305  )/x', $typeDetails['showitem'], $paletteMatches);
306  if ($paletteCount > 0) {
307  $paletteNames = array_filter(array_merge($paletteMatches[1], $paletteMatches[2]));
308  if (!empty($paletteNames)) {
309  foreach ($paletteNames as $paletteName) {
310  $palette = $GLOBALS['TCA'][$table]['palettes'][$paletteName];
311  switch ($positionIdentifier) {
312  case 'after':
313  case 'before':
314  if (preg_match('/\\b' . $entityName . '\\b/', $palette['showitem']) > 0) {
315  $newPosition = $positionIdentifier . ':--palette--;;' . $paletteName;
316  }
317  break;
318  case 'replace':
319  // check if fields have been added to palette before
320  if (isset($palettesChanged[$paletteName])) {
321  $fieldExists = TRUE;
322  continue;
323  }
324  if (preg_match('/\\b' . $entityName . '\\b/', $palette['showitem']) > 0) {
325  self::addFieldsToPalette($table, $paletteName, $newFieldsString, $position);
326  // Memorize that we already changed this palette, in case other types also use it
327  $palettesChanged[$paletteName] = TRUE;
328  $fieldExists = TRUE;
329  continue;
330  }
331  break;
332  default:
333  // Intentionally left blank
334  }
335  }
336  }
337  }
338  }
339  if ($fieldExists === FALSE) {
340  $typeDetails['showitem'] = self::executePositionedStringInsertion(
341  $typeDetails['showitem'],
342  $newFieldsString,
343  $newPosition !== '' ? $newPosition : $position
344  );
345  }
346  }
347  unset($typeDetails);
348  }
349 
361  static public function addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition = '') {
362  $generatedPalette = '';
363  $processedPalettes = array();
364  if (isset($GLOBALS['TCA'][$table]['columns'][$field])) {
365  $types = &$GLOBALS['TCA'][$table]['types'];
366  if (is_array($types)) {
367  // Iterate through all types and search for the field that defines the palette to be extended:
368  foreach ($types as $type => $_) {
369  $items = self::explodeItemList($types[$type]['showitem']);
370  if (isset($items[$field])) {
371  // If the field already has a palette, extend it:
372  if ($items[$field]['details']['palette']) {
373  $palette = $items[$field]['details']['palette'];
374  if (!isset($processedPalettes[$palette])) {
375  self::addFieldsToPalette($table, $palette, $addFields, $insertionPosition);
376  $processedPalettes[$palette] = TRUE;
377  }
378  } else {
379  if ($generatedPalette) {
380  $palette = $generatedPalette;
381  } else {
382  $palette = ($generatedPalette = 'generatedFor-' . $field);
383  self::addFieldsToPalette($table, $palette, $addFields, $insertionPosition);
384  }
385  $items[$field]['details']['palette'] = $palette;
386  $types[$type]['showitem'] = self::generateItemList($items);
387  }
388  }
389  }
390  }
391  }
392  }
393 
404  static public function addFieldsToPalette($table, $palette, $addFields, $insertionPosition = '') {
405  if (isset($GLOBALS['TCA'][$table])) {
406  $paletteData = &$GLOBALS['TCA'][$table]['palettes'][$palette];
407  // If palette already exists, merge the data:
408  if (is_array($paletteData)) {
409  $paletteData['showitem'] = self::executePositionedStringInsertion($paletteData['showitem'], $addFields, $insertionPosition);
410  } else {
411  $paletteData['showitem'] = self::removeDuplicatesForInsertion($addFields);
412  }
413  }
414  }
415 
444  static public function addTcaSelectItem($table, $field, array $item, $relativeToField = '', $relativePosition = '') {
445  if (!is_string($table)) {
446  throw new \InvalidArgumentException('Given table is of type "' . gettype($table) . '" but a string is expected.', 1303236963);
447  }
448  if (!is_string($field)) {
449  throw new \InvalidArgumentException('Given field is of type "' . gettype($field) . '" but a string is expected.', 1303236964);
450  }
451  if (!is_string($relativeToField)) {
452  throw new \InvalidArgumentException('Given relative field is of type "' . gettype($relativeToField) . '" but a string is expected.', 1303236965);
453  }
454  if (!is_string($relativePosition)) {
455  throw new \InvalidArgumentException('Given relative position is of type "' . gettype($relativePosition) . '" but a string is expected.', 1303236966);
456  }
457  if ($relativePosition !== '' && $relativePosition !== 'before' && $relativePosition !== 'after' && $relativePosition !== 'replace') {
458  throw new \InvalidArgumentException('Relative position must be either empty or one of "before", "after", "replace".', 1303236967);
459  }
460  if (!is_array($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])) {
461  throw new \RuntimeException('Given select field item list was not found.', 1303237468);
462  }
463  // Make sure item keys are integers
464  $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] = array_values($GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
465  if (strlen($relativePosition) > 0) {
466  // Insert at specified position
467  $matchedPosition = \TYPO3\CMS\Core\Utility\ArrayUtility::filterByValueRecursive($relativeToField, $GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
468  if (count($matchedPosition) > 0) {
469  $relativeItemKey = key($matchedPosition);
470  if ($relativePosition === 'replace') {
471  $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][$relativeItemKey] = $item;
472  } else {
473  if ($relativePosition === 'before') {
474  $offset = $relativeItemKey;
475  } else {
476  $offset = $relativeItemKey + 1;
477  }
478  array_splice($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'], $offset, 0, array(0 => $item));
479  }
480  } else {
481  // Insert at new item at the end of the array if relative position was not found
482  $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
483  }
484  } else {
485  // Insert at new item at the end of the array
486  $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
487  }
488  }
489 
500  static public function getFileFieldTCAConfig($fieldName, array $customSettingOverride = array(), $allowedFileExtensions = '', $disallowedFileExtensions = '') {
501  $fileFieldTCAConfig = array(
502  'type' => 'inline',
503  'foreign_table' => 'sys_file_reference',
504  'foreign_field' => 'uid_foreign',
505  'foreign_sortby' => 'sorting_foreign',
506  'foreign_table_field' => 'tablenames',
507  'foreign_match_fields' => array(
508  'fieldname' => $fieldName
509  ),
510  'foreign_label' => 'uid_local',
511  'foreign_selector' => 'uid_local',
512  'foreign_selector_fieldTcaOverride' => array(
513  'config' => array(
514  'appearance' => array(
515  'elementBrowserType' => 'file',
516  'elementBrowserAllowed' => $allowedFileExtensions
517  )
518  )
519  ),
520  'filter' => array(
521  array(
522  'userFunc' => 'TYPO3\\CMS\\Core\\Resource\\Filter\\FileExtensionFilter->filterInlineChildren',
523  'parameters' => array(
524  'allowedFileExtensions' => $allowedFileExtensions,
525  'disallowedFileExtensions' => $disallowedFileExtensions
526  )
527  )
528  ),
529  'appearance' => array(
530  'useSortable' => TRUE,
531  'headerThumbnail' => array(
532  'field' => 'uid_local',
533  'width' => '45',
534  'height' => '45c',
535  ),
536  'showPossibleLocalizationRecords' => FALSE,
537  'showRemovedLocalizationRecords' => FALSE,
538  'showSynchronizationLink' => FALSE,
539  'showAllLocalizationLink' => FALSE,
540 
541  'enabledControls' => array(
542  'info' => TRUE,
543  'new' => FALSE,
544  'dragdrop' => TRUE,
545  'sort' => FALSE,
546  'hide' => TRUE,
547  'delete' => TRUE,
548  'localize' => TRUE,
549  ),
550  ),
551  'behaviour' => array(
552  'localizationMode' => 'select',
553  'localizeChildrenAtParentLocalization' => TRUE,
554  ),
555  );
556  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($fileFieldTCAConfig, $customSettingOverride);
557  return $fileFieldTCAConfig;
558  }
559 
569  static public function addFieldsToUserSettings($addFields, $insertionPosition = '') {
570  $GLOBALS['TYPO3_USER_SETTINGS']['showitem'] = self::executePositionedStringInsertion($GLOBALS['TYPO3_USER_SETTINGS']['showitem'], $addFields, $insertionPosition);
571  }
572 
590  static protected function executePositionedStringInsertion($list, $insertionList, $insertionPosition = '') {
591  $list = $newList = trim($list, ", \t\n\r\0\x0B");
592 
593  list($location, $positionName) = GeneralUtility::trimExplode(':', $insertionPosition);
594 
595  if ($location !== 'replace') {
596  $insertionList = self::removeDuplicatesForInsertion($insertionList, $list);
597  }
598 
599  if ($insertionList === '') {
600  return $list;
601  }
602  if ($list === '') {
603  return $insertionList;
604  }
605  if ($insertionPosition === '') {
606  return $list . ', ' . $insertionList;
607  }
608 
609  // The $insertPosition may be a palette: after:--palette--;;title
610  // In the $list the palette may contain a LLL string in between the ;;
611  // Adjust the regex to match that
612  if (strpos($positionName, ';;') !== FALSE) {
613  $positionName = str_replace(';;', ';[^;]*;', $positionName);
614  }
615 
616  $pattern = ('/(^|,\\s*)(' . $positionName . ')(;[^,$]+)?(,|$)/');
617  switch ($location) {
618  case 'after':
619  $newList = preg_replace($pattern, '$1$2$3, ' . $insertionList . '$4', $list);
620  break;
621  case 'before':
622  $newList = preg_replace($pattern, '$1' . $insertionList . ', $2$3$4', $list);
623  break;
624  case 'replace':
625  $newList = preg_replace($pattern, '$1' . $insertionList . '$4', $list);
626  break;
627  default:
628  }
629 
630  // When preg_replace did not replace anything; append the $insertionList.
631  if ($list === $newList) {
632  return $list . ', ' . $insertionList;
633  }
634  return $newList;
635  }
636 
652  static protected function removeDuplicatesForInsertion($insertionList, $list = '') {
653  $insertionListParts = preg_split('/\\s*,\\s*/', $insertionList);
654  $listMatches = array();
655  if ($list !== '') {
656  preg_match_all('/(?:^|,)\\s*\\b([^;,]+)\\b[^,]*/', $list, $listMatches);
657  $listMatches = $listMatches[1];
658  }
659 
660  $cleanInsertionListParts = array();
661  foreach ($insertionListParts as $fieldName) {
662  $fieldNameParts = explode(';', $fieldName, 2);
663  $cleanFieldName = $fieldNameParts[0];
664  if (
665  $cleanFieldName === '--linebreak--'
666  || (
667  !in_array($cleanFieldName, $cleanInsertionListParts, TRUE)
668  && !in_array($cleanFieldName, $listMatches, TRUE)
669  )
670  ) {
671  $cleanInsertionListParts[] = $fieldName;
672  }
673  }
674  return implode(', ', $cleanInsertionListParts);
675  }
676 
686  static protected function getInsertionNeedles($item, array $itemDetails) {
687  if (strpos($item, '--') !== FALSE) {
688  // 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.
689  $item = str_replace(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), '', $item);
690  }
691  $needles = array(
692  'before' => array($item, 'before:' . $item),
693  'after' => array('after:' . $item),
694  'replace' => array('replace:' . $item)
695  );
696  if ($itemDetails['palette']) {
697  $palette = $item . ';;' . $itemDetails['palette'];
698  $needles['before'][] = $palette;
699  $needles['before'][] = 'before:' . $palette;
700  $needles['after'][] = 'after:' . $palette;
701  $needles['replace'][] = 'replace:' . $palette;
702  }
703  return $needles;
704  }
705 
712  static protected function explodeItemList($itemList) {
713  $items = array();
714  $itemParts = GeneralUtility::trimExplode(',', $itemList, TRUE);
715  foreach ($itemParts as $itemPart) {
716  $itemDetails = GeneralUtility::trimExplode(';', $itemPart, FALSE, 5);
717  $key = $itemDetails[0];
718  if (strpos($key, '--') !== FALSE) {
719  // 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!
720  $key .= count($items);
721  }
722  if (!isset($items[$key])) {
723  $items[$key] = array(
724  'rawData' => $itemPart,
725  'details' => array(
726  'field' => $itemDetails[0],
727  'label' => $itemDetails[1],
728  'palette' => $itemDetails[2],
729  'special' => $itemDetails[3],
730  'styles' => $itemDetails[4]
731  )
732  );
733  }
734  }
735  return $items;
736  }
737 
746  static protected function generateItemList(array $items, $useRawData = FALSE) {
747  $itemParts = array();
748  foreach ($items as $item => $itemDetails) {
749  if (strpos($item, '--') !== FALSE) {
750  // 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.
751  $item = str_replace(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), '', $item);
752  }
753  if ($useRawData) {
754  $itemParts[] = $itemDetails['rawData'];
755  } else {
756  $itemParts[] = count($itemDetails['details']) > 1 ? implode(';', $itemDetails['details']) : $item;
757  }
758  }
759  return implode(', ', $itemParts);
760  }
761 
770  static public function allowTableOnStandardPages($table) {
771  $GLOBALS['PAGES_TYPES']['default']['allowedTables'] .= ',' . $table;
772  }
773 
786  static public function addExtJSModule($extensionName, $mainModuleName, $subModuleName = '', $position = '', array $moduleConfiguration = array()) {
787  if (empty($extensionName)) {
788  throw new \InvalidArgumentException('The extension name must not be empty', 1325938973);
789  }
790  $extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName);
791  $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName)));
792  $defaultModuleConfiguration = array(
793  'access' => 'admin',
794  'icon' => 'gfx/typo3.png',
795  'labels' => '',
796  'extRelPath' => self::extRelPath($extensionKey) . 'Classes/'
797  );
798  // Add mandatory parameter to use new pagetree
799  if ($mainModuleName === 'web') {
800  $defaultModuleConfiguration['navigationComponentId'] = 'typo3-pagetree';
801  }
802  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($defaultModuleConfiguration, $moduleConfiguration);
803  $moduleConfiguration = $defaultModuleConfiguration;
804  if (strlen($subModuleName) > 0) {
805  $moduleSignature = $mainModuleName . '_' . $subModuleName;
806  } else {
807  $moduleSignature = $mainModuleName;
808  }
809  $moduleConfiguration['name'] = $moduleSignature;
810  $moduleConfiguration['script'] = 'extjspaneldummy.html';
811  $moduleConfiguration['extensionName'] = $extensionName;
812  $moduleConfiguration['configureModuleFunction'] = array('TYPO3\\CMS\\Core\\Utility\\ExtensionManagementUtility', 'configureModule');
813  $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature] = $moduleConfiguration;
814  self::addModule($mainModuleName, $subModuleName, $position);
815  }
816 
829  static public function configureModule($moduleSignature, $modulePath) {
830  $moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature];
831  $iconPathAndFilename = $moduleConfiguration['icon'];
832  if (substr($iconPathAndFilename, 0, 4) === 'EXT:') {
833  list($extensionKey, $relativePath) = explode('/', substr($iconPathAndFilename, 4), 2);
834  $iconPathAndFilename = self::extPath($extensionKey) . $relativePath;
835  }
836  // TODO: skin support
837  $moduleLabels = array(
838  'tabs_images' => array(
839  'tab' => $iconPathAndFilename
840  ),
841  'labels' => array(
842  'tablabel' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_labels_tablabel'),
843  'tabdescr' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_labels_tabdescr')
844  ),
845  'tabs' => array(
846  'tab' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_tabs_tab')
847  )
848  );
849  $GLOBALS['LANG']->addModuleLabels($moduleLabels, $moduleSignature . '_');
850  return $moduleConfiguration;
851  }
852 
864  static public function addModule($main, $sub = '', $position = '', $path = '', $moduleConfiguration = array()) {
865  // If there is already a main module by this name:
866  // Adding the submodule to the correct position:
867  if (isset($GLOBALS['TBE_MODULES'][$main]) && $sub) {
868  list($place, $modRef) = GeneralUtility::trimExplode(':', $position, TRUE);
869  $modules = ',' . $GLOBALS['TBE_MODULES'][$main] . ',';
870  if ($place === NULL || ($modRef !== NULL && !GeneralUtility::inList($modules, $modRef))) {
871  $place = 'bottom';
872  }
873  $modRef = ',' . $modRef . ',';
874  if (!GeneralUtility::inList($modules, $sub)) {
875  switch (strtolower($place)) {
876  case 'after':
877  $modules = str_replace($modRef, $modRef . $sub . ',', $modules);
878  break;
879  case 'before':
880  $modules = str_replace($modRef, ',' . $sub . $modRef, $modules);
881  break;
882  case 'top':
883  $modules = $sub . $modules;
884  break;
885  case 'bottom':
886  default:
887  $modules = $modules . $sub;
888  }
889  }
890  // Re-inserting the submodule list:
891  $GLOBALS['TBE_MODULES'][$main] = trim($modules, ',');
892  } else {
893  // Create new main modules with only one submodule, $sub (or none if $sub is blank)
894  $GLOBALS['TBE_MODULES'][$main] = $sub;
895  }
896  $fullModuleSignature = $main . ($sub ? '_' . $sub : '');
897  // Adding path:
898  if ($path) {
899  if (substr($path, 0, 4) === 'EXT:') {
900  list($extensionKey, $relativePath) = explode('/', substr($path, 4), 2);
901  $path = self::extPath($extensionKey) . $relativePath;
902  }
903 
904  $GLOBALS['TBE_MODULES']['_PATHS'][$fullModuleSignature] = $path;
905  }
906 
907  // add additional configuration
908  if (is_array($moduleConfiguration) && count($moduleConfiguration) > 0) {
909  $GLOBALS['TBE_MODULES']['_configuration'][$fullModuleSignature] = $moduleConfiguration;
910  }
911  }
912 
922  static public function registerExtDirectComponent($endpointName, $callbackClass, $moduleName = NULL, $accessLevel = NULL) {
923  $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'][$endpointName] = array(
924  'callbackClass' => $callbackClass,
925  'moduleName' => $moduleName,
926  'accessLevel' => $accessLevel
927  );
928  }
929 
937  static public function registerAjaxHandler($ajaxId, $callbackMethod, $csrfTokenCheck = TRUE) {
938  $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX'][$ajaxId] = array(
939  'callbackMethod' => $callbackMethod,
940  'csrfTokenCheck' => $csrfTokenCheck
941  );
942  }
943 
955  static public function addModulePath($name, $path) {
956  if (substr($path, 0, 4) === 'EXT:') {
957  list($extensionKey, $relativePath) = explode('/', substr($path, 4), 2);
958  $path = ExtensionManagementUtility::extPath($extensionKey) . $relativePath;
959  }
960  $GLOBALS['TBE_MODULES']['_PATHS'][$name] = $path;
961  }
962 
978  static public function insertModuleFunction($modname, $className, $classPath, $title, $MM_key = 'function', $WS = '') {
979  if (!empty($classPath)) {
981  sprintf('insertModuleFunction(%s, %s, ...): Use auto-loading for the class and pass NULL as $classPath since 6.2.',
982  $modname,
983  $className
984  )
985  );
986  }
987  $GLOBALS['TBE_MODULES_EXT'][$modname]['MOD_MENU'][$MM_key][$className] = array(
988  'name' => $className,
989  'path' => $classPath,
990  'title' => $title,
991  'ws' => $WS
992  );
993  }
994 
1007  static public function appendToTypoConfVars($group, $key, $content) {
1008  $GLOBALS['TYPO3_CONF_VARS_extensionAdded'][$group][$key] .= $content;
1009  $GLOBALS['TYPO3_CONF_VARS'][$group][$key] .= $content;
1010  }
1011 
1020  static public function addPageTSConfig($content) {
1021  self::appendToTypoConfVars('BE', 'defaultPageTSconfig', '
1022 [GLOBAL]
1023 ' . $content);
1024  }
1025 
1034  static public function addUserTSConfig($content) {
1035  self::appendToTypoConfVars('BE', 'defaultUserTSconfig', '
1036 [GLOBAL]
1037 ' . $content);
1038  }
1039 
1049  static public function addLLrefForTCAdescr($tca_descr_key, $file_ref) {
1050  if ($tca_descr_key) {
1051  if (!is_array($GLOBALS['TCA_DESCR'][$tca_descr_key])) {
1052  $GLOBALS['TCA_DESCR'][$tca_descr_key] = array();
1053  }
1054  if (!is_array($GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'])) {
1055  $GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'] = array();
1056  }
1057  $GLOBALS['TCA_DESCR'][$tca_descr_key]['refs'][] = $file_ref;
1058  }
1059  }
1060 
1070  static public function addNavigationComponent($module, $componentId, $extensionKey = NULL) {
1071  $extensionKey = $extensionKey ?: $GLOBALS['_EXTKEY'];
1072  if (!isset($extensionKey)) {
1073  throw new \RuntimeException('No extensionKey set in addNavigationComponent(). Provide it as third Parameter', 1404068039);
1074  }
1075  $GLOBALS['TBE_MODULES']['_navigationComponents'][$module] = array(
1076  'componentId' => $componentId,
1077  'extKey' => $extensionKey,
1078  'isCoreComponent' => FALSE
1079  );
1080  }
1081 
1089  static public function addCoreNavigationComponent($module, $componentId) {
1090  self::addNavigationComponent($module, $componentId);
1091  $GLOBALS['TBE_MODULES']['_navigationComponents'][$module]['isCoreComponent'] = TRUE;
1092  }
1093 
1094  /**************************************
1095  *
1096  * Adding SERVICES features
1097  *
1098  ***************************************/
1108  static public function addService($extKey, $serviceType, $serviceKey, $info) {
1109  if ($serviceType && is_array($info)) {
1110  $info['priority'] = max(0, min(100, $info['priority']));
1111  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = $info;
1112  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['extKey'] = $extKey;
1113  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceKey'] = $serviceKey;
1114  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceType'] = $serviceType;
1115  // Change the priority (and other values) from $GLOBALS['TYPO3_CONF_VARS']
1116  // $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]['priority']
1117  // even the activation is possible (a unix service might be possible on windows for some reasons)
1118  if (is_array($GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey])) {
1119  // No check is done here - there might be configuration values only the service type knows about, so
1120  // we pass everything
1121  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey] = array_merge($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey], $GLOBALS['TYPO3_CONF_VARS']['T3_SERVICES'][$serviceType][$serviceKey]);
1122  }
1123  // OS check
1124  // Empty $os means 'not limited to one OS', therefore a check is not needed
1125  if ($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] && $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os'] != '') {
1126  // TYPO3_OS is not yet defined
1127  $os_type = stripos(PHP_OS, 'win') !== FALSE && !stripos(PHP_OS, 'darwin') !== FALSE ? 'WIN' : 'UNIX';
1128  $os = GeneralUtility::trimExplode(',', strtoupper($GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['os']));
1129  if (!in_array($os_type, $os)) {
1130  self::deactivateService($serviceType, $serviceKey);
1131  }
1132  }
1133  // Convert subtype list to array for quicker access
1134  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'] = array();
1135  $serviceSubTypes = GeneralUtility::trimExplode(',', $info['subtype']);
1136  foreach ($serviceSubTypes as $subtype) {
1137  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['serviceSubTypes'][$subtype] = $subtype;
1138  }
1139  }
1140  }
1141 
1150  static public function findService($serviceType, $serviceSubType = '', $excludeServiceKeys = array()) {
1151  $serviceKey = FALSE;
1152  $serviceInfo = FALSE;
1153  $priority = 0;
1154  $quality = 0;
1155  if (!is_array($excludeServiceKeys)) {
1156  $excludeServiceKeys = GeneralUtility::trimExplode(',', $excludeServiceKeys, TRUE);
1157  }
1158  if (is_array($GLOBALS['T3_SERVICES'][$serviceType])) {
1159  foreach ($GLOBALS['T3_SERVICES'][$serviceType] as $key => $info) {
1160  if (in_array($key, $excludeServiceKeys)) {
1161  continue;
1162  }
1163  // Select a subtype randomly
1164  // Useful to start a service by service key without knowing his subtypes - for testing purposes
1165  if ($serviceSubType == '*') {
1166  $serviceSubType = key($info['serviceSubTypes']);
1167  }
1168  // This matches empty subtype too
1169  if ($info['available'] && ($info['subtype'] == $serviceSubType || $info['serviceSubTypes'][$serviceSubType]) && $info['priority'] >= $priority) {
1170  // Has a lower quality than the already found, therefore we skip this service
1171  if ($info['priority'] == $priority && $info['quality'] < $quality) {
1172  continue;
1173  }
1174  // Check if the service is available
1175  $info['available'] = self::isServiceAvailable($serviceType, $key, $info);
1176  // Still available after exec check?
1177  if ($info['available']) {
1178  $serviceKey = $key;
1179  $priority = $info['priority'];
1180  $quality = $info['quality'];
1181  }
1182  }
1183  }
1184  }
1185  if ($serviceKey) {
1186  $serviceInfo = $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey];
1187  }
1188  return $serviceInfo;
1189  }
1190 
1199  static public function findServiceByKey($serviceKey) {
1200  if (is_array($GLOBALS['T3_SERVICES'])) {
1201  // Loop on all service types
1202  // NOTE: we don't care about the actual type, we are looking for a specific key
1203  foreach ($GLOBALS['T3_SERVICES'] as $serviceType => $servicesPerType) {
1204  if (isset($servicesPerType[$serviceKey])) {
1205  $serviceDetails = $servicesPerType[$serviceKey];
1206  // Test if service is available
1207  if (self::isServiceAvailable($serviceType, $serviceKey, $serviceDetails)) {
1208  // We have found the right service, return its information
1209  return $serviceDetails;
1210  }
1211  }
1212  }
1213  }
1214  throw new \TYPO3\CMS\Core\Exception('Service not found for key: ' . $serviceKey, 1319217244);
1215  }
1216 
1225  static public function isServiceAvailable($serviceType, $serviceKey, $serviceDetails) {
1226  // If the service depends on external programs - check if they exists
1227  if (trim($serviceDetails['exec'])) {
1228  $executables = GeneralUtility::trimExplode(',', $serviceDetails['exec'], TRUE);
1229  foreach ($executables as $executable) {
1230  // If at least one executable file is not available, exit early returning FALSE
1231  if (!\TYPO3\CMS\Core\Utility\CommandUtility::checkCommand($executable)) {
1232  self::deactivateService($serviceType, $serviceKey);
1233  return FALSE;
1234  }
1235  }
1236  }
1237  // The service is available
1238  return TRUE;
1239  }
1240 
1248  static public function deactivateService($serviceType, $serviceKey) {
1249  // ... maybe it's better to move non-available services to a different array??
1250  $GLOBALS['T3_SERVICES'][$serviceType][$serviceKey]['available'] = FALSE;
1251  }
1252 
1253  /**************************************
1254  *
1255  * Adding FRONTEND features
1256  * (related specifically to "cms" extension)
1257  *
1258  ***************************************/
1272  static public function addPlugin($itemArray, $type = 'list_type', $extensionKey = NULL) {
1273  $extensionKey = $extensionKey ?: $GLOBALS['_EXTKEY'];
1274  if (!isset($extensionKey)) {
1275  throw new \RuntimeException(
1276  'No extension key could be determined when calling addPlugin()!'
1277  . LF
1278  . 'This method is meant to be called from an ext_tables.php or Configuration/TCA/Overrides file. '
1279  . 'If you call it from Configuration/TCA/Overrides, the extension key needs to be specified as third parameter. '
1280  . 'Calling it from any other place e.g. ext_localconf.php does not work and is not supported.',
1281  1404068038
1282  );
1283  }
1284  if ($extensionKey && !$itemArray[2] && isset($GLOBALS['TYPO3_LOADED_EXT'][$extensionKey]['ext_icon'])) {
1285  $itemArray[2] = self::extRelPath($extensionKey) . $GLOBALS['TYPO3_LOADED_EXT'][$extensionKey]['ext_icon'];
1286  }
1287  if (is_array($GLOBALS['TCA']['tt_content']['columns']) && is_array($GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'])) {
1288  foreach ($GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'] as $k => $v) {
1289  if ((string)$v[1] === (string)$itemArray[1]) {
1290  $GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][$k] = $itemArray;
1291  return;
1292  }
1293  }
1294  $GLOBALS['TCA']['tt_content']['columns'][$type]['config']['items'][] = $itemArray;
1295  }
1296  }
1297 
1308  static public function addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch = 'list') {
1309  if (is_array($GLOBALS['TCA']['tt_content']['columns']) && is_array($GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'])) {
1310  $GLOBALS['TCA']['tt_content']['columns']['pi_flexform']['config']['ds'][$piKeyToMatch . ',' . $CTypeToMatch] = $value;
1311  }
1312  }
1313 
1324  static public function addToInsertRecords($table, $content_table = 'tt_content', $content_field = 'records') {
1325  if (is_array($GLOBALS['TCA'][$content_table]['columns']) && isset($GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'])) {
1326  $GLOBALS['TCA'][$content_table]['columns'][$content_field]['config']['allowed'] .= ',' . $table;
1327  }
1328  }
1329 
1358  static public function addPItoST43($key, $classFile = '', $prefix = '', $type = 'list_type', $cached = 0) {
1359  $classFile = $classFile ? $classFile : 'pi/class.tx_' . str_replace('_', '', $key) . $prefix . '.php';
1360  $cN = self::getCN($key);
1361  // General plugin
1362  $pluginContent = trim('
1363 plugin.' . $cN . $prefix . ' = USER' . ($cached ? '' : '_INT') . '
1364 plugin.' . $cN . $prefix . ' {
1365  includeLibs = ' . $GLOBALS['TYPO3_LOADED_EXT'][$key]['siteRelPath'] . $classFile . '
1366  userFunc = ' . $cN . $prefix . '->main
1367 }');
1368  self::addTypoScript($key, 'setup', '
1369 # Setting ' . $key . ' plugin TypoScript
1370 ' . $pluginContent);
1371  // Add after defaultContentRendering
1372  switch ($type) {
1373  case 'list_type':
1374  $addLine = 'tt_content.list.20.' . $key . $prefix . ' = < plugin.' . $cN . $prefix;
1375  break;
1376  case 'menu_type':
1377  $addLine = 'tt_content.menu.20.' . $key . $prefix . ' = < plugin.' . $cN . $prefix;
1378  break;
1379  case 'CType':
1380  $addLine = trim('
1381 tt_content.' . $key . $prefix . ' = COA
1382 tt_content.' . $key . $prefix . ' {
1383  10 = < lib.stdheader
1384  20 = < plugin.' . $cN . $prefix . '
1385 }
1386 ');
1387  break;
1388  case 'header_layout':
1389  $addLine = 'lib.stdheader.10.' . $key . $prefix . ' = < plugin.' . $cN . $prefix;
1390  break;
1391  case 'includeLib':
1392  $addLine = 'page.1000 = < plugin.' . $cN . $prefix;
1393  break;
1394  default:
1395  $addLine = '';
1396  }
1397  if ($addLine) {
1398  self::addTypoScript($key, 'setup', '
1399 # Setting ' . $key . ' plugin TypoScript
1400 ' . $addLine . '
1401 ', 'defaultContentRendering');
1402  }
1403  }
1404 
1415  static public function addStaticFile($extKey, $path, $title) {
1416  if ($extKey && $path && is_array($GLOBALS['TCA']['sys_template']['columns'])) {
1417  $value = str_replace(',', '', 'EXT:' . $extKey . '/' . $path);
1418  $itemArray = array(trim($title . ' (' . $extKey . ')'), $value);
1419  $GLOBALS['TCA']['sys_template']['columns']['include_static_file']['config']['items'][] = $itemArray;
1420  }
1421  }
1422 
1431  static public function addTypoScriptSetup($content) {
1432  self::appendToTypoConfVars('FE', 'defaultTypoScript_setup', '
1433 [GLOBAL]
1434 ' . $content);
1435  }
1436 
1445  static public function addTypoScriptConstants($content) {
1446  self::appendToTypoConfVars('FE', 'defaultTypoScript_constants', '
1447 [GLOBAL]
1448 ' . $content);
1449  }
1450 
1469  static public function addTypoScript($key, $type, $content, $afterStaticUid = 0) {
1470  if ($type === 'setup' || $type === 'constants') {
1471  $content = '
1472 
1473 [GLOBAL]
1474 #############################################
1475 ## TypoScript added by extension "' . $key . '"
1476 #############################################
1477 
1478 ' . $content;
1479  if ($afterStaticUid) {
1480  // If 'content (default)' is targeted (static uid 43),
1481  // the content is added after typoscript of type contentRendering, eg. css_styled_content, see EXT:frontend/TemplateService for more information on how the code is parsed
1482  if ($afterStaticUid === 'defaultContentRendering' || $afterStaticUid == 43) {
1483  $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.']['defaultContentRendering'] .= $content;
1484  } else {
1485  $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type . '.'][$afterStaticUid] .= $content;
1486  }
1487  } else {
1488  $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_' . $type] .= $content;
1489  }
1490  }
1491  }
1492 
1493  /***************************************
1494  *
1495  * Internal extension management methods
1496  *
1497  ***************************************/
1506  static public function getExtensionIcon($extensionPath, $returnFullPath = FALSE) {
1507  $icon = '';
1508  $iconFileTypesToCheckFor = array('png', 'gif');
1509  foreach ($iconFileTypesToCheckFor as $fileType) {
1510  if (file_exists($extensionPath . 'ext_icon.' . $fileType)) {
1511  $icon = 'ext_icon.' . $fileType;
1512  break;
1513  }
1514  }
1515  return $returnFullPath ? $extensionPath . $icon : $icon;
1516  }
1517 
1530  static public function loadExtLocalconf($allowCaching = TRUE) {
1531  if ($allowCaching) {
1532  $cacheIdentifier = self::getExtLocalconfCacheIdentifier();
1534  $codeCache = self::getCacheManager()->getCache('cache_core');
1535  if ($codeCache->has($cacheIdentifier)) {
1536  $codeCache->requireOnce($cacheIdentifier);
1537  } else {
1538  self::loadSingleExtLocalconfFiles();
1539  self::createExtLocalconfCacheEntry();
1540  }
1541  } else {
1542  self::loadSingleExtLocalconfFiles();
1543  }
1544  }
1545 
1551  static protected function loadSingleExtLocalconfFiles() {
1552  // This is the main array meant to be manipulated in the ext_localconf.php files
1553  // In general it is recommended to not rely on it to be globally defined in that
1554  // scope but to use $GLOBALS['TYPO3_CONF_VARS'] instead.
1555  // Nevertheless we define it here as global for backwards compatibility.
1556  global $TYPO3_CONF_VARS;
1557  foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $_EXTKEY => $extensionInformation) {
1558  if ((is_array($extensionInformation) || $extensionInformation instanceof \ArrayAccess) && isset($extensionInformation['ext_localconf.php'])) {
1559  // $_EXTKEY and $_EXTCONF are available in ext_localconf.php
1560  // and are explicitly set in cached file as well
1561  $_EXTCONF = isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]) ? $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY] : NULL;
1562  require $extensionInformation['ext_localconf.php'];
1563  }
1564  }
1565  }
1566 
1572  static protected function createExtLocalconfCacheEntry() {
1573  $extensionInformation = $GLOBALS['TYPO3_LOADED_EXT'];
1574  $phpCodeToCache = array();
1575  // Set same globals as in loadSingleExtLocalconfFiles()
1576  $phpCodeToCache[] = '';
1579  $phpCodeToCache[] = '';
1580  $phpCodeToCache[] = 'global $TYPO3_CONF_VARS, $T3_SERVICES, $T3_VAR;';
1581  $phpCodeToCache[] = '';
1582  // Iterate through loaded extensions and add ext_localconf content
1583  foreach ($extensionInformation as $extensionKey => $extensionDetails) {
1584  if (isset($extensionDetails['ext_localconf.php']) && $extensionDetails['ext_localconf.php']) {
1585  // Include a header per extension to make the cache file more readable
1586  $phpCodeToCache[] = '';
1590  $phpCodeToCache[] = '';
1591  // Set $_EXTKEY and $_EXTCONF for this extension
1592  $phpCodeToCache[] = '$_EXTKEY = \'' . $extensionKey . '\';';
1593  $phpCodeToCache[] = '$_EXTCONF = $GLOBALS[\'TYPO3_CONF_VARS\'][\'EXT\'][\'extConf\'][$_EXTKEY];';
1594  $phpCodeToCache[] = '';
1595  // Add ext_localconf.php content of extension
1596  $phpCodeToCache[] = trim(GeneralUtility::getUrl($extensionDetails['ext_localconf.php']));
1597  $phpCodeToCache[] = '';
1598  $phpCodeToCache[] = '';
1599  }
1600  }
1601  $phpCodeToCache = implode(LF, $phpCodeToCache);
1602  // Remove all start and ending php tags from content
1603  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1604  self::getCacheManager()->getCache('cache_core')->set(self::getExtLocalconfCacheIdentifier(), $phpCodeToCache);
1605  }
1606 
1612  static protected function getExtLocalconfCacheIdentifier() {
1613  return 'ext_localconf_' . sha1(TYPO3_version . PATH_site . 'extLocalconf' . serialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1614  }
1615 
1630  static public function loadBaseTca($allowCaching = TRUE) {
1631  if ($allowCaching) {
1632  $cacheIdentifier = static::getBaseTcaCacheIdentifier();
1634  $codeCache = static::getCacheManager()->getCache('cache_core');
1635  if ($codeCache->has($cacheIdentifier)) {
1636  // substr is necessary, because the php frontend wraps php code around the cache value
1637  $cacheData = unserialize(substr($codeCache->get($cacheIdentifier), 6, -2));
1638  $GLOBALS['TCA'] = $cacheData['tca'];
1639  GeneralUtility::setSingletonInstance('TYPO3\\CMS\\Core\\Category\\CategoryRegistry', $cacheData['categoryRegistry']);
1640  } else {
1641  static::buildBaseTcaFromSingleFiles();
1642  static::createBaseTcaCacheFile();
1643  }
1644  } else {
1645  static::buildBaseTcaFromSingleFiles();
1646  }
1647  }
1648 
1657  static protected function buildBaseTcaFromSingleFiles() {
1658  $GLOBALS['TCA'] = array();
1659 
1660  $activePackages = static::$packageManager->getActivePackages();
1661 
1662  // First load "full table" files from Configuration/TCA
1663  foreach ($activePackages as $package) {
1664  $tcaConfigurationDirectory = $package->getPackagePath() . 'Configuration/TCA';
1665  if (is_dir($tcaConfigurationDirectory)) {
1666  $files = scandir($tcaConfigurationDirectory);
1667  foreach ($files as $file) {
1668  if (
1669  is_file($tcaConfigurationDirectory . '/' . $file)
1670  && ($file !== '.')
1671  && ($file !== '..')
1672  && (substr($file, -4, 4) === '.php')
1673  ) {
1674  $tcaOfTable = require($tcaConfigurationDirectory . '/' . $file);
1675  if (is_array($tcaOfTable)) {
1676  // TCA table name is filename without .php suffix, eg 'sys_notes', not 'sys_notes.php'
1677  $tcaTableName = substr($file, 0, -4);
1678  $GLOBALS['TCA'][$tcaTableName] = $tcaOfTable;
1679  }
1680  }
1681  }
1682  }
1683  }
1684 
1685  // Apply category stuff
1686  \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance()->applyTcaForPreRegisteredTables();
1687 
1688  // Execute override files from Configuration/TCA/Overrides
1689  foreach ($activePackages as $package) {
1690  $tcaOverridesPathForPackage = $package->getPackagePath() . 'Configuration/TCA/Overrides';
1691  if (is_dir($tcaOverridesPathForPackage)) {
1692  $files = scandir($tcaOverridesPathForPackage);
1693  foreach ($files as $file) {
1694  if (
1695  is_file($tcaOverridesPathForPackage . '/' . $file)
1696  && ($file !== '.')
1697  && ($file !== '..')
1698  && (substr($file, -4, 4) === '.php')
1699  ) {
1700  require($tcaOverridesPathForPackage . '/' . $file);
1701  }
1702  }
1703  }
1704  }
1705 
1706  static::emitTcaIsBeingBuiltSignal($GLOBALS['TCA']);
1707  }
1708 
1719  static protected function emitTcaIsBeingBuiltSignal(array $tca) {
1720  list($tca) = static::getSignalSlotDispatcher()->dispatch(__CLASS__, 'tcaIsBeingBuilt', array($tca));
1721  $GLOBALS['TCA'] = $tca;
1722  }
1723 
1730  static protected function createBaseTcaCacheFile() {
1732  $codeCache = self::getCacheManager()->getCache('cache_core');
1733  $codeCache->set(static::getBaseTcaCacheIdentifier(), serialize(array('tca' => $GLOBALS['TCA'], 'categoryRegistry' => \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance())));
1734  }
1735 
1741  static protected function getBaseTcaCacheIdentifier() {
1742  return 'tca_base_' . sha1(TYPO3_version . PATH_site . 'tca_with_category_registry' . serialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1743  }
1744 
1757  static public function loadExtTables($allowCaching = TRUE) {
1758  if ($allowCaching && !self::$extTablesWasReadFromCacheOnce) {
1759  self::$extTablesWasReadFromCacheOnce = TRUE;
1760  $cacheIdentifier = self::getExtTablesCacheIdentifier();
1762  $codeCache = self::getCacheManager()->getCache('cache_core');
1763  if ($codeCache->has($cacheIdentifier)) {
1764  $codeCache->requireOnce($cacheIdentifier);
1765  } else {
1766  self::loadSingleExtTablesFiles();
1767  self::createExtTablesCacheEntry();
1768  }
1769  } else {
1770  self::loadSingleExtTablesFiles();
1771  }
1772  }
1773 
1779  static protected function loadSingleExtTablesFiles() {
1780  // In general it is recommended to not rely on it to be globally defined in that
1781  // scope, but we can not prohibit this without breaking backwards compatibility
1782  global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;
1783  global $TBE_MODULES, $TBE_MODULES_EXT, $TCA;
1784  global $PAGES_TYPES, $TBE_STYLES, $FILEICONS;
1785  global $_EXTKEY;
1786  // Load each ext_tables.php file of loaded extensions
1787  foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $_EXTKEY => $extensionInformation) {
1788  if ((is_array($extensionInformation) || $extensionInformation instanceof \ArrayAccess) && $extensionInformation['ext_tables.php']) {
1789  // $_EXTKEY and $_EXTCONF are available in ext_tables.php
1790  // and are explicitly set in cached file as well
1791  $_EXTCONF = $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY];
1792  require $extensionInformation['ext_tables.php'];
1793  static::loadNewTcaColumnsConfigFiles();
1794  }
1795  }
1796  }
1797 
1803  static protected function createExtTablesCacheEntry() {
1804  $extensionInformation = $GLOBALS['TYPO3_LOADED_EXT'];
1805  $phpCodeToCache = array();
1806  // Set same globals as in loadSingleExtTablesFiles()
1807  $phpCodeToCache[] = '';
1810  $phpCodeToCache[] = '';
1811  $phpCodeToCache[] = 'global $T3_SERVICES, $T3_VAR, $TYPO3_CONF_VARS;';
1812  $phpCodeToCache[] = 'global $TBE_MODULES, $TBE_MODULES_EXT, $TCA;';
1813  $phpCodeToCache[] = 'global $PAGES_TYPES, $TBE_STYLES, $FILEICONS;';
1814  $phpCodeToCache[] = 'global $_EXTKEY;';
1815  $phpCodeToCache[] = '';
1816  // Iterate through loaded extensions and add ext_tables content
1817  foreach ($extensionInformation as $extensionKey => $extensionDetails) {
1818  if (isset($extensionDetails['ext_tables.php']) && $extensionDetails['ext_tables.php']) {
1819  // Include a header per extension to make the cache file more readable
1820  $phpCodeToCache[] = '';
1824  $phpCodeToCache[] = '';
1825  // Set $_EXTKEY and $_EXTCONF for this extension
1826  $phpCodeToCache[] = '$_EXTKEY = \'' . $extensionKey . '\';';
1827  $phpCodeToCache[] = '$_EXTCONF = $GLOBALS[\'TYPO3_CONF_VARS\'][\'EXT\'][\'extConf\'][$_EXTKEY];';
1828  $phpCodeToCache[] = '';
1829  // Add ext_tables.php content of extension
1830  $phpCodeToCache[] = trim(GeneralUtility::getUrl($extensionDetails['ext_tables.php']));
1831  $phpCodeToCache[] = '';
1832  $phpCodeToCache[] = '\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::loadNewTcaColumnsConfigFiles();';
1833  $phpCodeToCache[] = '';
1834  }
1835  }
1836  $phpCodeToCache = implode(LF, $phpCodeToCache);
1837  // Remove all start and ending php tags from content
1838  $phpCodeToCache = preg_replace('/<\\?php|\\?>/is', '', $phpCodeToCache);
1839  self::getCacheManager()->getCache('cache_core')->set(self::getExtTablesCacheIdentifier(), $phpCodeToCache);
1840  }
1841 
1862  static public function loadNewTcaColumnsConfigFiles() {
1863  global $TCA;
1864 
1865  foreach ($TCA as $tableName => $_) {
1866  if (!isset($TCA[$tableName]['columns'])) {
1867  $columnsConfigFile = $TCA[$tableName]['ctrl']['dynamicConfigFile'];
1868  if ($columnsConfigFile) {
1869  if (GeneralUtility::isAbsPath($columnsConfigFile)) {
1870  include($columnsConfigFile);
1871  } else {
1872  throw new \RuntimeException(
1873  'Columns configuration file not found',
1874  1341151261
1875  );
1876  }
1877  }
1878  }
1879  }
1880  }
1881 
1887  static protected function getExtTablesCacheIdentifier() {
1888  return 'ext_tables_' . sha1(TYPO3_version . PATH_site . 'extTables' . serialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['runtimeActivatedPackages']));
1889  }
1890 
1898  static public function isLocalconfWritable() {
1900  return GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager')
1901  ->canWriteConfiguration();
1902  }
1903 
1919  static public function removeCacheFiles() {
1920  self::getCacheManager()->flushCachesInGroup('system');
1921  }
1922 
1928  static public function getLoadedExtensionListArray() {
1929  return array_keys(static::$packageManager->getActivePackages());
1930  }
1931 
1938  static public function getRequiredExtensionListArray() {
1940  return GeneralUtility::trimExplode(',', REQUIRED_EXTENSIONS);
1941  }
1942 
1953  static public function loadExtension($extensionKey) {
1954  if (static::$packageManager->isPackageActive($extensionKey)) {
1955  throw new \RuntimeException('Extension already loaded', 1342345486);
1956  }
1957  static::$packageManager->activatePackage($extensionKey);
1958  }
1959 
1970  static public function unloadExtension($extensionKey) {
1971  if (!static::$packageManager->isPackageActive($extensionKey)) {
1972  throw new \RuntimeException('Extension not loaded', 1342345487);
1973  }
1974  static::$packageManager->deactivatePackage($extensionKey);
1975  }
1976 
1987  static public function writeNewExtensionList(array $newExtensionList) {
1989  }
1990 
2002  static public function makeCategorizable($extensionKey, $tableName, $fieldName = 'categories', array $options = array()) {
2003  // Update the category registry
2004  $result = \TYPO3\CMS\Core\Category\CategoryRegistry::getInstance()->add($extensionKey, $tableName, $fieldName, $options);
2005  if ($result === FALSE) {
2006  $message = '\TYPO3\CMS\Core\Category\CategoryRegistry: no category registered for table "%s". Key was already registered.';
2008  $logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__);
2009  $logger->warning(
2010  sprintf($message, $tableName)
2011  );
2012  }
2013  }
2014 }
static addFieldsToAllPalettesOfField($table, $field, $addFields, $insertionPosition='')
static registerAjaxHandler($ajaxId, $callbackMethod, $csrfTokenCheck=TRUE)
static addFieldsToUserSettings($addFields, $insertionPosition='')
static checkCommand($cmd, $handler='')
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=TRUE, $includeEmptyValues=TRUE, $enableUnsetFeature=TRUE)
static getExtensionIcon($extensionPath, $returnFullPath=FALSE)
static addPItoST43($key, $classFile='', $prefix='', $type='list_type', $cached=0)
$TYPO3_CONF_VARS['SYS']['contentTable']
static setSingletonInstance($className, \TYPO3\CMS\Core\SingletonInterface $instance)
static getFileFieldTCAConfig($fieldName, array $customSettingOverride=array(), $allowedFileExtensions='', $disallowedFileExtensions='')
static addService($extKey, $serviceType, $serviceKey, $info)
$moduleName
Definition: mod.php:22
static addToInsertRecords($table, $content_table='tt_content', $content_field='records')
if(!defined('TYPO3_MODE')) $pluginContent
$TCA['tx_irretutorial_1ncsv_hotel']
static setPackageManager(\TYPO3\CMS\Core\Package\PackageManager $packageManager)
static addTypoScript($key, $type, $content, $afterStaticUid=0)
static addTCAcolumns($table, $columnArray, $addTofeInterface=FALSE)
static addPlugin($itemArray, $type='list_type', $extensionKey=NULL)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
static addPiFlexFormValue($piKeyToMatch, $value, $CTypeToMatch='list')
static insertModuleFunction($modname, $className, $classPath, $title, $MM_key='function', $WS='')
$addLine
static addNavigationComponent($module, $componentId, $extensionKey=NULL)
static registerExtDirectComponent($endpointName, $callbackClass, $moduleName=NULL, $accessLevel=NULL)
static addToAllTCAtypes($table, $newFieldsString, $typeList='', $position='')
$csrfTokenCheck
Definition: ajax.php:49
static filterByValueRecursive($needle='', array $haystack=array())
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
static addExtJSModule($extensionName, $mainModuleName, $subModuleName='', $position='', array $moduleConfiguration=array())
static getUrl($url, $includeHeader=0, $requestHeaders=FALSE, &$report=NULL)
static isServiceAvailable($serviceType, $serviceKey, $serviceDetails)
if(!defined('TYPO3_MODE')) $_EXTCONF
static generateItemList(array $items, $useRawData=FALSE)
$signalSlotDispatcher
static addTcaSelectItem($table, $field, array $item, $relativeToField='', $relativePosition='')
static addModule($main, $sub='', $position='', $path='', $moduleConfiguration=array())
static executePositionedStringInsertion($list, $insertionList, $insertionPosition='')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static findService($serviceType, $serviceSubType='', $excludeServiceKeys=array())
static addFieldsToPalette($table, $palette, $addFields, $insertionPosition='')