[BUGFIX] No double htmlspecialchars for filemount select
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Utility / ExtensionUtility.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * Utilities to manage plugins and modules of an extension. Also useful to auto-generate the autoloader registry
32 * file ext_autoload.php.
33 */
34 class ExtensionUtility {
35
36 const PLUGIN_TYPE_PLUGIN = 'list_type';
37 const PLUGIN_TYPE_CONTENT_ELEMENT = 'CType';
38
39 /**
40 * Add auto-generated TypoScript to configure the Extbase Dispatcher.
41 *
42 * When adding a frontend plugin you will have to add both an entry to the TCA definition
43 * of tt_content table AND to the TypoScript template which must initiate the rendering.
44 * Since the static template with uid 43 is the "content.default" and practically always
45 * used for rendering the content elements it's very useful to have this function automatically
46 * adding the necessary TypoScript for calling the appropriate controller and action of your plugin.
47 * It will also work for the extension "css_styled_content"
48 * FOR USE IN ext_localconf.php FILES
49 * Usage: 2
50 *
51 * @param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore)
52 * @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!)
53 * @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)
54 * @param array $nonCacheableControllerActions is an optional array of controller name and action names which should not be cached (array as defined in $controllerActions)
55 * @param string $pluginType either \TYPO3\CMS\Extbase\Utility\ExtensionUtility::TYPE_PLUGIN (default) or \TYPO3\CMS\Extbase\Utility\ExtensionUtility::TYPE_CONTENT_ELEMENT
56 * @throws \InvalidArgumentException
57 * @return void
58 */
59 static public function configurePlugin($extensionName, $pluginName, array $controllerActions, array $nonCacheableControllerActions = array(), $pluginType = self::PLUGIN_TYPE_PLUGIN) {
60 if (empty($pluginName)) {
61 throw new \InvalidArgumentException('The plugin name must not be empty', 1239891987);
62 }
63 if (empty($extensionName)) {
64 throw new \InvalidArgumentException('The extension name was invalid (must not be empty and must match /[A-Za-z][_A-Za-z0-9]/)', 1239891989);
65 }
66 // Check if vendor name is prepended to extensionName in the format {vendorName}.{extensionName}
67 $vendorName = NULL;
68 $delimiterPosition = strrpos($extensionName, '.');
69 if ($delimiterPosition !== FALSE) {
70 $vendorName = str_replace('.', '\\', substr($extensionName, 0, $delimiterPosition));
71 $extensionName = substr($extensionName, $delimiterPosition + 1);
72 }
73 $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName)));
74 $pluginSignature = strtolower($extensionName) . '_' . strtolower($pluginName);
75 if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName])) {
76 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName] = array();
77 }
78 foreach ($controllerActions as $controllerName => $actionsList) {
79 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName] = array('actions' => \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $actionsList));
80 if (!empty($nonCacheableControllerActions[$controllerName])) {
81 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName]['nonCacheableActions'] = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $nonCacheableControllerActions[$controllerName]);
82 }
83 }
84 $pluginTemplate = 'plugin.tx_' . strtolower($extensionName) . ' {
85 settings {
86 }
87 persistence {
88 storagePid =
89 classes {
90 }
91 }
92 view {
93 templateRootPath =
94 layoutRootPath =
95 partialRootPath =
96 # with defaultPid you can specify the default page uid of this plugin. If you set this to the string "auto" the target page will be determined automatically. Defaults to an empty string that expects the target page to be the current page.
97 defaultPid =
98 }
99 }';
100 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript($extensionName, 'setup', '
101 # Setting ' . $extensionName . ' plugin TypoScript
102 ' . $pluginTemplate);
103 switch ($pluginType) {
104 case self::PLUGIN_TYPE_PLUGIN:
105 $pluginContent = trim('
106 tt_content.list.20.' . $pluginSignature . ' = USER
107 tt_content.list.20.' . $pluginSignature . ' {
108 userFunc = TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run
109 extensionName = ' . $extensionName . '
110 pluginName = ' . $pluginName . (NULL !== $vendorName ? ("\n\t" . 'vendorName = ' . $vendorName) : '') . '
111 }');
112 break;
113 case self::PLUGIN_TYPE_CONTENT_ELEMENT:
114 $pluginContent = trim('
115 tt_content.' . $pluginSignature . ' = COA
116 tt_content.' . $pluginSignature . ' {
117 10 = < lib.stdheader
118 20 = USER
119 20 {
120 userFunc = TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run
121 extensionName = ' . $extensionName . '
122 pluginName = ' . $pluginName . (NULL !== $vendorName ? ("\n\t\t" . 'vendorName = ' . $vendorName) : '') . '
123 }
124 }');
125 break;
126 default:
127 throw new \InvalidArgumentException('The pluginType "' . $pluginType . '" is not suported', 1289858856);
128 }
129 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['pluginType'] = $pluginType;
130 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScript($extensionName, 'setup', '
131 # Setting ' . $extensionName . ' plugin TypoScript
132 ' . $pluginContent, 43);
133 }
134
135 /**
136 * Register an Extbase PlugIn into backend's list of plugins
137 * FOR USE IN ext_tables.php FILES
138 *
139 * @param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore)
140 * @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!)
141 * @param string $pluginTitle is a speaking title of the plugin that will be displayed in the drop down menu in the backend
142 * @param string $pluginIconPathAndFilename is a path to an icon file (relative to TYPO3_mainDir), that will be displayed in the drop down menu in the backend (optional)
143 * @throws \InvalidArgumentException
144 * @return void
145 */
146 static public function registerPlugin($extensionName, $pluginName, $pluginTitle, $pluginIconPathAndFilename = NULL) {
147 if (empty($pluginName)) {
148 throw new \InvalidArgumentException('The plugin name must not be empty', 1239891987);
149 }
150 if (empty($extensionName)) {
151 throw new \InvalidArgumentException('The extension name was invalid (must not be empty and must match /[A-Za-z][_A-Za-z0-9]/)', 1239891989);
152 }
153 $delimiterPosition = strrpos($extensionName, '.');
154 if ($delimiterPosition !== FALSE) {
155 $extensionName = substr($extensionName, $delimiterPosition + 1);
156 }
157 $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName)));
158 $pluginSignature = strtolower($extensionName) . '_' . strtolower($pluginName);
159 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin(array($pluginTitle, $pluginSignature, $pluginIconPathAndFilename), $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['pluginType']);
160 }
161
162 /**
163 * This method is called from \TYPO3\CMS\Backend\Module\ModuleLoader::checkMod
164 * and it replaces old conf.php.
165 *
166 * @param string $moduleSignature The module name
167 * @param string $modulePath Absolute path to module (not used by Extbase currently)
168 * @return array Configuration of the module
169 */
170 static public function configureModule($moduleSignature, $modulePath) {
171 $moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature];
172 $iconPathAndFilename = $moduleConfiguration['icon'];
173 if (substr($iconPathAndFilename, 0, 4) === 'EXT:') {
174 list($extensionKey, $relativePath) = explode('/', substr($iconPathAndFilename, 4), 2);
175 $iconPathAndFilename = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($extensionKey) . $relativePath;
176 }
177 // TODO: skin support
178 $moduleLabels = array(
179 'tabs_images' => array(
180 'tab' => $iconPathAndFilename
181 ),
182 'labels' => array(
183 'tablabel' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_labels_tablabel'),
184 'tabdescr' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_labels_tabdescr')
185 ),
186 'tabs' => array(
187 'tab' => $GLOBALS['LANG']->sL($moduleConfiguration['labels'] . ':mlang_tabs_tab')
188 )
189 );
190 $GLOBALS['LANG']->addModuleLabels($moduleLabels, $moduleSignature . '_');
191 return $moduleConfiguration;
192 }
193
194 /**
195 * Registers an Extbase module (main or sub) to the backend interface.
196 * FOR USE IN ext_tables.php FILES
197 *
198 * @param string $extensionName The extension name (in UpperCamelCase) or the extension key (in lower_underscore)
199 * @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
200 * @param string $subModuleName The submodule key.
201 * @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.
202 * @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)
203 * @param array $moduleConfiguration The configuration options of the module (icon, locallang.xlf file)
204 * @throws \InvalidArgumentException
205 * @return void
206 */
207 static public function registerModule($extensionName, $mainModuleName = '', $subModuleName = '', $position = '', array $controllerActions, array $moduleConfiguration = array()) {
208 if (empty($extensionName)) {
209 throw new \InvalidArgumentException('The extension name must not be empty', 1239891989);
210 }
211 // Check if vendor name is prepended to extensionName in the format {vendorName}.{extensionName}
212 $vendorName = NULL;
213 if (FALSE !== $delimiterPosition = strrpos($extensionName, '.')) {
214 $vendorName = str_replace('.', '\\', substr($extensionName, 0, $delimiterPosition));
215 $extensionName = substr($extensionName, $delimiterPosition + 1);
216 }
217 $extensionKey = \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName);
218 $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName)));
219 $defaultModuleConfiguration = array(
220 'access' => 'admin',
221 'icon' => 'EXT:extbase/ext_icon.gif',
222 'labels' => '',
223 'extRelPath' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($extensionKey) . 'Classes/'
224 );
225 if (strlen($mainModuleName) > 0 && !array_key_exists($mainModuleName, $GLOBALS['TBE_MODULES'])) {
226 $mainModuleName = $extensionName . \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($mainModuleName);
227 } else {
228 $mainModuleName = strlen($mainModuleName) > 0 ? $mainModuleName : 'web';
229 }
230 // add mandatory parameter to use new pagetree
231 if ($mainModuleName === 'web') {
232 $defaultModuleConfiguration['navigationComponentId'] = 'typo3-pagetree';
233 }
234 $moduleConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($defaultModuleConfiguration, $moduleConfiguration);
235 $moduleSignature = $mainModuleName;
236 if (strlen($subModuleName) > 0) {
237 $subModuleName = $extensionName . \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($subModuleName);
238 $moduleSignature .= '_' . $subModuleName;
239 }
240 $moduleConfiguration['name'] = $moduleSignature;
241 $moduleConfiguration['script'] = 'mod.php?M=' . rawurlencode($moduleSignature);
242 if (NULL !== $vendorName) {
243 $moduleConfiguration['vendorName'] = $vendorName;
244 }
245 $moduleConfiguration['extensionName'] = $extensionName;
246 $moduleConfiguration['configureModuleFunction'] = array('TYPO3\\CMS\\Extbase\\Utility\\ExtensionUtility', 'configureModule');
247 $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature] = $moduleConfiguration;
248 if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature])) {
249 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature] = array();
250 }
251 foreach ($controllerActions as $controllerName => $actions) {
252 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$moduleSignature]['controllers'][$controllerName] = array(
253 'actions' => \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $actions)
254 );
255 }
256 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule($mainModuleName, $subModuleName, $position);
257 }
258
259 /**
260 * Register a type converter by class name.
261 *
262 * @param string $typeConverterClassName
263 * @return void
264 * @api
265 */
266 static public function registerTypeConverter($typeConverterClassName) {
267 if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'])) {
268 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'] = array();
269 }
270 $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['typeConverters'][] = $typeConverterClassName;
271 }
272 }