Index: tests/t3lib/t3lib_extmgm_testcase.php =================================================================== --- tests/t3lib/t3lib_extmgm_testcase.php (Revision 5427) +++ tests/t3lib/t3lib_extmgm_testcase.php (Arbeitskopie) @@ -31,18 +31,35 @@ * @subpackage t3lib */ class t3lib_extmgm_testcase extends tx_phpunit_testcase { + /** * Contains backup of defined GLOBALS * @var array */ protected $globals = array(); + /** + * Contains backup of $TYPO3_CONF_VARS + * @var array + */ + protected $typo3ConfVars = array(); + public function setUp() { + global $TYPO3_CONF_VARS; + $this->typo3ConfVars = $TYPO3_CONF_VARS; $this->globals = array( 'TYPO3_LOADED_EXT' => serialize($GLOBALS['TYPO3_LOADED_EXT']), ); } - + + public function tearDown() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS = $this->typo3ConfVars; + foreach ($this->globals as $key => $value) { + $GLOBALS[$key] = unserialize($value); + } + } + /** * @test * @see t3lib_extMgm::getExtensionKeyByPrefix @@ -64,12 +81,277 @@ t3lib_extMgm::getExtensionKeyByPrefix('tx_unloadedextension' . $uniqueSuffix) ); } + - public function tearDown() { - foreach ($this->globals as $key => $value) { - $GLOBALS[$key] = unserialize($value); + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingTsWorksForMinimalisticSetup() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array('Blog' => 'index') + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains('tt_content.list.20.myextension_pi1 = USER', $staticTypoScript); + $this->assertContains(' + pluginName = pi1 + extensionName = MyExtension', $staticTypoScript); + + $this->assertNotContains('USER_INT', $staticTypoScript); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingTsWorksForASingleControllerAction() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index' + ) + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains('tt_content.list.20.myextension_pi1 = USER', $staticTypoScript); + $this->assertContains(' + pluginName = pi1 + extensionName = MyExtension + controller = FirstController + action = index', $staticTypoScript); + $this->assertNotContains('USER_INT', $staticTypoScript); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWithEmptyPluginNameResultsInAnError() { + $this->setExpectedException('InvalidArgumentException'); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + '', + 'My Plugin Title', + array( + 'FirstController' => 'index' + ) + ); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWithEmptyExtensionKeyResultsInAnError() { + $this->setExpectedException('InvalidArgumentException'); + t3lib_extMgm::addExtbasePlugin( + '', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index' + ) + ); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWithInvalidExtensionKeyResultsInAnError() { + $this->setExpectedException('InvalidArgumentException'); + t3lib_extMgm::addExtbasePlugin( + 'MyExtension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index' + ) + ); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginRespectsDefaultActionAsANonCachableAction() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index,show,new,create,delete,edit,update' + ), + array( + 'FirstController' => 'index,show' + ) + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains(' +tt_content.list.20.myextension_pi1 = USER_INT +tt_content.list.20.myextension_pi1 {', $staticTypoScript); + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = FirstController] && [globalString: GP = tx_myextension_pi1|action = /new|create|delete|edit|update/] +tt_content.list.20.myextension_pi1 = USER', $staticTypoScript); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginRespectsNonDefaultActionAsANonCachableAction() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index,show,new,create,delete,edit,update' + ), + array( + 'FirstController' => 'show,new' + ) + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains(' +tt_content.list.20.myextension_pi1 = USER +tt_content.list.20.myextension_pi1 {', $staticTypoScript); + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = FirstController] && [globalString: GP = tx_myextension_pi1|action = /show|new/] +tt_content.list.20.myextension_pi1 = USER_INT', $staticTypoScript); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWorksForMultipleControllerActionsWithCachableActionAsDefault() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index,show,new,create,delete,edit,update', + 'SecondController' => 'index,show,delete', + 'ThirdController' => 'create' + ), + array( + 'FirstController' => 'new,create,edit,update', + 'SecondController' => 'delete', + 'ThirdController' => 'create' + ), + array('SecondController' => 'show') + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains(' +tt_content.list.20.myextension_pi1 = USER +tt_content.list.20.myextension_pi1 {', $staticTypoScript); + + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = FirstController] && [globalString: GP = tx_myextension_pi1|action = /new|create|edit|update/] +tt_content.list.20.myextension_pi1 = USER_INT', $staticTypoScript); + + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = SecondController] && [globalString: GP = tx_myextension_pi1|action = /delete/] +tt_content.list.20.myextension_pi1 = USER_INT', $staticTypoScript); + + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = ThirdController] && [globalString: GP = tx_myextension_pi1|action = /create/] +tt_content.list.20.myextension_pi1 = USER_INT', $staticTypoScript); + } + + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWorksForMultipleControllerActionsWithNonCachableActionAsDefault() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index,show,new,create,delete,edit,update', + 'SecondController' => 'index,show,delete', + 'ThirdController' => 'create' + ), + array( + 'FirstController' => 'index,new,create,edit,update', + 'SecondController' => 'delete', + 'ThirdController' => 'create' + ) + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains(' +tt_content.list.20.myextension_pi1 = USER_INT +tt_content.list.20.myextension_pi1 {', $staticTypoScript); + + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = FirstController] && [globalString: GP = tx_myextension_pi1|action = /show|delete/] +tt_content.list.20.myextension_pi1 = USER', $staticTypoScript); + + $this->assertContains(' +[globalString: GP = tx_myextension_pi1|controller = SecondController] && [globalString: GP = tx_myextension_pi1|action = /index|show/] +tt_content.list.20.myextension_pi1 = USER', $staticTypoScript); + + $this->assertNotContains('[globalString: GP = tx_myextension_pi1|controller = ThirdController]', $staticTypoScript); + } + + /** + * @test + * @see t3lib_extMgm::addExtbasePlugin + */ + public function addingPluginWorksForMultipleControllerActionsWithNonCachableActionAsDefaultAndOnlyNonCachableActions() { + global $TYPO3_CONF_VARS; + $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.'] = array(); + t3lib_extMgm::addExtbasePlugin( + 'my_extension', + 'pi1', + 'My Plugin Title', + array( + 'FirstController' => 'index,show,new,create,delete,edit,update', + 'SecondController' => 'index,show,delete', + 'ThirdController' => 'create' + ), + array( + 'FirstController' => 'index,show,new,create,delete,edit,update', + 'SecondController' => 'index,show,delete', + 'ThirdController' => 'create' + ) + ); + $staticTypoScript = $TYPO3_CONF_VARS['FE']['defaultTypoScript_setup.']['43']; + + $this->assertContains(' +tt_content.list.20.myextension_pi1 = USER_INT +tt_content.list.20.myextension_pi1 {', $staticTypoScript); + + $this->assertNotContains('GP', $staticTypoScript); } - } + + // TODO switchableControllerActionsIsSupressedIfOnlyOneControllerActionIsGiven() + // TODO switchableControllerDingsIsGeneratedWithMultipleControllersEachHavingOnlyOneAction + } ?> \ No newline at end of file Index: t3lib/class.t3lib_extmgm.php =================================================================== --- t3lib/class.t3lib_extmgm.php (Revision 5427) +++ t3lib/class.t3lib_extmgm.php (Arbeitskopie) @@ -1066,7 +1066,109 @@ ', 43); } } + + /** + * Add an Extbase PlugIn to TypoScript + * + * When adding a frontend plugin you will have to add both an entry to the TCA definition + * of tt_content table AND to the TypoScript template which must initiate the rendering. + * Since the static template with uid 43 is the "content.default" and practically always + * used for rendering the content elements it's very useful to have this function automatically + * adding the necessary TypoScript for calling your plugin. It will also work for the + * extension "css_styled_content" + * FOR USE IN ext_locallang.php FILES + * Usage: 2 + * + * @param string $extensionKey is the extension key in lower_underscore (available in $_EXTKEY) + * @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 $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 string $nonCachableControllerActions is an optional array of controller name and action names which should not be cached (array as defined in $controllerActions) + * @param string $defaultControllerAction is an optional array controller name (as array key) and action name (as array value) that should be called as default + * @return void + */ + public static function addExtbasePlugin($extensionKey, $pluginName, $pluginTitle, array $controllerActions, array $nonCachableControllerActions = array()) { + if (empty($pluginName)) { + throw new InvalidArgumentException('The plugin name must not be empty', 1239891987); + } + if (empty($extensionKey) || preg_match('/[^_a-z0-9]/', $extensionKey) === 1) { + throw new InvalidArgumentException('The extension key was invalid (must not be empty and must match [_a-z0-9])', 1239891989); + } + $extensionName = t3lib_div::underscoredToUpperCamelCase($extensionKey); + $pluginSignature = strtolower($extensionName) . '_' . strtolower($pluginName); + + $controllerCounter = 1; + $hasMultipleActionsCounter = 0; + $controllers = ''; + foreach ($controllerActions as $controller => $actionsList) { + $controllers .= ' + ' . $controllerCounter . '.controller = ' . $controller . ' + ' . $controllerCounter . '.actions = ' . $actionsList; + $controllerCounter++; + if (strpos($actionsList, ',') !== FALSE) { + $hasMultipleActionsCounter++; + } + } + + $switchableControllerActions = ''; + if ($controllerCounter > 1 || $hasMultipleActionsCounter > 0) { + $switchableControllerActions = ' + switchableControllerActions {' . $controllers . ' + }'; + } + + reset($controllerActions); + $defaultController = key($controllerActions); + $controller = ' + controller = ' . $defaultController; + $defaultAction = array_shift(t3lib_div::trimExplode(',', current($controllerActions))); + $action = ' + action = ' . $defaultAction; + $nonCachableActions = array(); + if (!empty($nonCachableControllerActions[$defaultController])) { + $nonCachableActions = t3lib_div::trimExplode(',', $nonCachableControllerActions[$defaultController]); + } + $cachableActions = array_diff(t3lib_div::trimExplode(',', $controllerActions[$defaultController]), $nonCachableActions); + + $contentObjectType = in_array($defaultAction, $nonCachableActions) ? 'USER_INT' : 'USER'; + + $conditions = ''; + foreach ($controllerActions as $controllerName => $actionsList) { + if (!empty($nonCachableControllerActions[$controllerName])) { + $nonCachableActions = t3lib_div::trimExplode(',', $nonCachableControllerActions[$controllerName]); + $cachableActions = array_diff(t3lib_div::trimExplode(',', $controllerActions[$controllerName]), $nonCachableActions); + if (($contentObjectType == 'USER' && count($nonCachableActions) > 0) + || ($contentObjectType == 'USER_INT' && count($cachableActions) > 0)) { + + $conditions .= ' +[globalString: GP = tx_' . $pluginSignature . '|controller = ' . $controllerName . '] && [globalString: GP = tx_' . $pluginSignature . '|action = /' . implode('|', $contentObjectType === 'USER' ? $nonCachableActions : $cachableActions) . '/] +tt_content.list.20.' . $pluginSignature . ' = ' . ($contentObjectType === 'USER' ? 'USER_INT' : 'USER') . ' +[global] +'; + } + } + } + + $pluginContent = trim(' +tt_content.list.20.' . $pluginSignature . ' = ' . $contentObjectType . ' +tt_content.list.20.' . $pluginSignature . ' { + userFunc = tx_extbase_dispatcher->dispatch + pluginName = ' . $pluginName . ' + extensionName = ' . $extensionName . + $controller . + $action . + $switchableControllerActions . ' +} +' . $conditions); + + t3lib_extMgm::addTypoScript($extensionKey, 'setup', ' +# Setting ' . $extensionKey . ' plugin TypoScript +' . $pluginContent, 43); + + self::addPlugin(array($pluginTitle, $pluginSignature), 'list_type'); + } + /** * Call this method to add an entry in the static template list found in sys_templates * "static template files" are the modern equalent (provided from extensions) to the traditional records in "static_templates"