$actionsList) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName] = ['actions' => \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $actionsList)]; if (!empty($nonCacheableControllerActions[$controllerName])) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName]['nonCacheableActions'] = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $nonCacheableControllerActions[$controllerName]); } } switch ($pluginType) { case self::PLUGIN_TYPE_PLUGIN: $pluginContent = trim(' tt_content.list.20.' . $pluginSignature . ' = USER tt_content.list.20.' . $pluginSignature . ' { userFunc = TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run extensionName = ' . $extensionName . ' pluginName = ' . $pluginName . (null !== $vendorName ? ("\n\t" . 'vendorName = ' . $vendorName) : '') . ' }'); break; case self::PLUGIN_TYPE_CONTENT_ELEMENT: $pluginContent = trim(' tt_content.' . $pluginSignature . ' =< lib.contentElement tt_content.' . $pluginSignature . ' { templateName = Generic 20 = USER 20 { userFunc = TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run extensionName = ' . $extensionName . ' pluginName = ' . $pluginName . (null !== $vendorName ? ("\n\t\t" . 'vendorName = ' . $vendorName) : '') . ' } }'); break; default: throw new \InvalidArgumentException('The pluginType "' . $pluginType . '" is not suported', 1289858856); } $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['pluginType'] = $pluginType; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript($extensionName, 'setup', ' # Setting ' . $extensionName . ' plugin TypoScript ' . $pluginContent, 'defaultContentRendering'); } /** * Register an Extbase PlugIn into backend's list of plugins * FOR USE IN Configuration/TCA/Overrides/tt_content.php * * @param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore) * @param string $pluginName must be a unique id for your plugin in UpperCamelCase (the string length of the extension key added to the length of the plugin name should be less than 32!) * @param string $pluginTitle is a speaking title of the plugin that will be displayed in the drop down menu in the backend * @param string $pluginIcon is an icon identifier or file path prepended with "EXT:", that will be displayed in the drop down menu in the backend (optional) * @throws \InvalidArgumentException */ public static function registerPlugin($extensionName, $pluginName, $pluginTitle, $pluginIcon = null) { self::checkPluginNameFormat($pluginName); self::checkExtensionNameFormat($extensionName); $delimiterPosition = strrpos($extensionName, '.'); if ($delimiterPosition !== false) { $extensionName = substr($extensionName, $delimiterPosition + 1); } $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName))); $pluginSignature = strtolower($extensionName) . '_' . strtolower($pluginName); // At this point $extensionName is normalized, no matter which format the method was feeded with. // Calculate the original extensionKey from this again. $extensionKey = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName); // pluginType is usually defined by configurePlugin() in the global array. Use this or fall back to default "list_type". $pluginType = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['pluginType'] ?? 'list_type'; \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin( [$pluginTitle, $pluginSignature, $pluginIcon], $pluginType, $extensionKey ); } /** * Registers an Extbase module (main or sub) to the backend interface. * FOR USE IN ext_tables.php FILES * * @param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore) * @param string $mainModuleName The main module key. So $main would be an index in the $TBE_MODULES array and $sub could be an element in the lists there. If $subModuleName is not set a blank $extensionName module is created * @param string $subModuleName The submodule key. * @param string $position This can be used to set the position of the $sub module within the list of existing submodules for the main module. $position has this syntax: [cmd]:[submodule-key]. cmd can be "after", "before" or "top" (or blank which is default). If "after"/"before" then submodule will be inserted after/before the existing submodule with [submodule-key] if found. If not found, the bottom of list. If "top" the module is inserted in the top of the submodule list. * @param array $controllerActions is an array of allowed combinations of controller and action stored in an array (controller name as key and a comma separated list of action names as value, the first controller and its first action is chosen as default) * @param array $moduleConfiguration The configuration options of the module (icon, locallang.xlf file) * @throws \InvalidArgumentException */ public static function registerModule($extensionName, $mainModuleName = '', $subModuleName = '', $position = '', array $controllerActions = [], array $moduleConfiguration = []) { self::checkExtensionNameFormat($extensionName); // Check if vendor name is prepended to extensionName in the format {vendorName}.{extensionName} $vendorName = null; if (false !== $delimiterPosition = strrpos($extensionName, '.')) { $vendorName = str_replace('.', '\\', substr($extensionName, 0, $delimiterPosition)); $extensionName = substr($extensionName, $delimiterPosition + 1); if (!empty($vendorName)) { self::checkVendorNameFormat($vendorName, $extensionName); } } $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName))); $defaultModuleConfiguration = [ 'access' => 'admin', 'icon' => 'EXT:extbase/Resources/Public/Icons/Extension.png', 'labels' => '' ]; if ($mainModuleName !== '' && !array_key_exists($mainModuleName, $GLOBALS['TBE_MODULES'])) { $mainModuleName = $extensionName . \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($mainModuleName); } else { $mainModuleName = $mainModuleName !== '' ? $mainModuleName : 'web'; } // add mandatory parameter to use new pagetree if ($mainModuleName === 'web') { $defaultModuleConfiguration['navigationComponentId'] = 'TYPO3/CMS/Backend/PageTree/PageTreeElement'; } \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($defaultModuleConfiguration, $moduleConfiguration); $moduleConfiguration = $defaultModuleConfiguration; $moduleSignature = $mainModuleName; if ($subModuleName !== '') { $subModuleName = $extensionName . \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($subModuleName); $moduleSignature .= '_' . $subModuleName; } $moduleConfiguration['name'] = $moduleSignature; if (null !== $vendorName) { $moduleConfiguration['vendorName'] = $vendorName; } $moduleConfiguration['extensionName'] = $extensionName; $moduleConfiguration['routeTarget'] = \TYPO3\CMS\Extbase\Core\Bootstrap::class . '::handleBackendRequest'; if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature] ?? false)) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature] = []; } foreach ($controllerActions as $controllerName => $actions) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature]['controllers'][$controllerName] = [ 'actions' => \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $actions) ]; } \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule($mainModuleName, $subModuleName, $position, null, $moduleConfiguration); } /** * Register a type converter by class name. * * @param string $typeConverterClassName */ public static function registerTypeConverter($typeConverterClassName) { if (!isset($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters']) || !is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters']) ) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'] = []; } if (!in_array($typeConverterClassName, $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'])) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'][] = $typeConverterClassName; } } /** * Check a given vendor name for CGL compliance. * Log a deprecation message if it is not. * * @param string $vendorName The vendor name to check * @param string $extensionName The extension name that is affected */ protected static function checkVendorNameFormat($vendorName, $extensionName) { if (preg_match('/^[A-Z]/', $vendorName) !== 1) { trigger_error('The vendor name from tx_' . $extensionName . ' must begin with a capital letter.', E_USER_DEPRECATED); } } /** * Check a given extension name for validity. * * @param string $extensionName The name of the extension * @throws \InvalidArgumentException */ protected static function checkExtensionNameFormat($extensionName) { if (empty($extensionName)) { throw new \InvalidArgumentException('The extension name must not be empty', 1239891990); } } /** * Check a given plugin name for validity. * * @param string $pluginName The name of the plugin * @throws \InvalidArgumentException */ protected static function checkPluginNameFormat($pluginName) { if (empty($pluginName)) { throw new \InvalidArgumentException('The plugin name must not be empty', 1239891988); } } }