[~TASK] Extbase: Reimplemented BE module support. Still needs cleanup.
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Configuration / FrontendConfigurationManager.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009 Jochen Rau <jochen.rau@typoplanet.de>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 /**
26 * A general purpose configuration manager used in frontend mode.
27 *
28 * Should NOT be singleton, as a new configuration manager is needed per plugin.
29 *
30 * @package Extbase
31 * @subpackage Configuration
32 * @version $ID:$
33 */
34 class Tx_Extbase_Configuration_FrontendConfigurationManager extends Tx_Extbase_Configuration_AbstractConfigurationManager {
35
36 /**
37 * Loads the Extbase Framework configuration.
38 *
39 * The Extbase framework configuration HAS TO be retrieved using this method, as they are come from different places than the normal settings.
40 * Framework configuration is, in contrast to normal settings, needed for the Extbase framework to operate correctly.
41 *
42 * @param string $configurationType The kind of configuration to fetch - must be one of the CONFIGURATION_TYPE_* constants
43 * @param string $extensionName if specified, the configuration for the given extension will be returned (plugin.tx_extensionname)
44 * @param string $pluginName if specified, the configuration for the given plugin will be returned (plugin.tx_extensionname_pluginname)
45 * @return array the Extbase framework configuration
46 */
47 public function getConfiguration($configurationType, $extensionName = NULL, $pluginName = NULL) {
48 // 1st level cache
49 if ($extensionName !== NULL) {
50 $configurationCacheKey = strtolower($extensionName);
51 if ($pluginName !== NULL) {
52 $configurationCacheKey .= '_' . strtolower($pluginName);
53 }
54 } else {
55 $configurationCacheKey = strtolower($this->extensionName . '_' . $this->pluginName);
56 }
57 if (isset($this->configurationCache[$configurationCacheKey])) {
58 return $this->configurationCache[$configurationCacheKey];
59 }
60
61 $frameworkConfiguration = array();
62 $frameworkConfiguration['persistence']['storagePid'] = self::DEFAULT_BACKEND_STORAGE_PID;
63
64 $setup = $this->getTypoScriptSetup();
65 if ($extensionName !== NULL) {
66 $pluginConfiguration = $setup['plugin.']['tx_' . strtolower($extensionName) . '.'];
67 if ($pluginName !== NULL) {
68 $pluginSignature = strtolower($extensionName . '_' . $pluginName);
69 if (is_array($setup['plugin.']['tx_' . $pluginSignature . '.'])) {
70 $pluginConfiguration = t3lib_div::array_merge_recursive_overrule($pluginConfiguration, $setup['plugin.']['tx_' . $pluginSignature . '.']);
71 }
72 }
73 } else {
74 $pluginConfiguration = $this->configuration;
75 }
76 $extbaseConfiguration = $setup['config.']['tx_extbase.'];
77 if (is_array($extbaseConfiguration)) {
78 $extbaseConfiguration = Tx_Extbase_Utility_TypoScript::convertTypoScriptArrayToPlainArray($extbaseConfiguration);
79 $frameworkConfiguration = t3lib_div::array_merge_recursive_overrule($frameworkConfiguration, $extbaseConfiguration);
80 }
81
82 if (isset($pluginConfiguration['settings'])) {
83 $pluginConfiguration = $this->resolveTyposcriptReference($pluginConfiguration, 'settings');
84 }
85 if (!is_array($pluginConfiguration['settings.'])) $pluginConfiguration['settings.'] = array(); // We expect that the settings are arrays on various places
86 if (isset($pluginConfiguration['persistence'])) {
87 $pluginConfiguration = $this->resolveTyposcriptReference($pluginConfiguration, 'persistence');
88 }
89 if (isset($pluginConfiguration['view'])) {
90 $pluginConfiguration = $this->resolveTyposcriptReference($pluginConfiguration, 'view');
91 }
92 if (isset($pluginConfiguration['_LOCAL_LANG'])) {
93 $pluginConfiguration = $this->resolveTyposcriptReference($pluginConfiguration, '_LOCAL_LANG');
94 }
95 $frameworkConfiguration = t3lib_div::array_merge_recursive_overrule($frameworkConfiguration, Tx_Extbase_Utility_TypoScript::convertTypoScriptArrayToPlainArray($pluginConfiguration));
96
97 // only load context specific configuration when retrieving configuration of the current plugin
98 if ($extensionName === NULL || ($extensionName === $this->extensionName && $pluginName === $this->pluginName)) {
99 $frameworkConfiguration = $this->getContextSpecificFrameworkConfiguration($frameworkConfiguration);
100 }
101
102 // 1st level cache
103 $this->configurationCache[$configurationCacheKey] = $frameworkConfiguration;
104 return $frameworkConfiguration;
105 }
106
107 /**
108 * Returns TypoScript Setup array from current Environment.
109 *
110 * @return array the raw TypoScript setup
111 */
112 public function getTypoScriptSetup() {
113 return $GLOBALS['TSFE']->tmpl->setup;
114 }
115
116 /**
117 * Get context specific framework configuration.
118 * - Overrides storage PID with setting "Startingpoint"
119 * - merge flexform configuration, if needed
120 *
121 * @param array $frameworkConfiguration The framework configuration to modify
122 * @return array the modified framework configuration
123 */
124 protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration) {
125 $frameworkConfiguration = $this->overrideStoragePidIfStartingPointIsSet($frameworkConfiguration);
126 $frameworkConfiguration = $this->overrideConfigurationFromPlugin($frameworkConfiguration);
127 $frameworkConfiguration = $this->overrideConfigurationFromFlexform($frameworkConfiguration);
128
129 return $frameworkConfiguration;
130 }
131
132 /**
133 * Overrides the storage PID settings, in case the "Startingpoint" settings
134 * is set in the plugin configuration.
135 *
136 * @param array $frameworkConfiguration the framework configurations
137 * @return array the framework configuration with overriden storagePid
138 */
139 protected function overrideStoragePidIfStartingPointIsSet(array $frameworkConfiguration) {
140 $pages = $this->contentObject->data['pages'];
141 if (is_string($pages) && strlen($pages) > 0) {
142 $list = array();
143 if($this->contentObject->data['recursive'] > 0) {
144 $explodedPages = t3lib_div::trimExplode(',', $pages);
145 foreach($explodedPages as $pid) {
146 $list[] = trim($this->contentObject->getTreeList($pid, $this->contentObject->data['recursive']), ',');
147 }
148 }
149 if (count($list) > 0) {
150 $pages = $pages . ',' . implode(',', $list);
151 }
152 $frameworkConfiguration = t3lib_div::array_merge_recursive_overrule($frameworkConfiguration, array(
153 'persistence' => array(
154 'storagePid' => $pages
155 )
156 ));
157 }
158 return $frameworkConfiguration;
159 }
160
161 /**
162 * Overrides configuration settings from the plugin typoscript (plugin.tx_myext_pi1.)
163 *
164 * @param array the framework configuration
165 * @return array the framework configuration with overridden data from typoscript
166 */
167 protected function overrideConfigurationFromPlugin(array $frameworkConfiguration) {
168 $setup = $this->getTypoScriptSetup();
169 $pluginSignature = strtolower($frameworkConfiguration['extensionName'] . '_' . $frameworkConfiguration['pluginName']);
170 $pluginConfiguration = $setup['plugin.']['tx_' . $pluginSignature . '.'];
171 if (is_array($pluginConfiguration)) {
172 $pluginConfiguration = Tx_Extbase_Utility_TypoScript::convertTypoScriptArrayToPlainArray($pluginConfiguration);
173 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'settings');
174 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'persistence');
175 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'view');
176 }
177 return $frameworkConfiguration;
178 }
179
180 /**
181 * Overrides configuration settings from flexforms.
182 * This merges the whole flexform data, and overrides switchable controller actions.
183 *
184 * @param array the framework configuration
185 * @return array the framework configuration with overridden data from flexform
186 */
187 protected function overrideConfigurationFromFlexform(array $frameworkConfiguration) {
188 if (strlen($this->contentObject->data['pi_flexform']) > 0) {
189 $flexformConfiguration = $this->convertFlexformContentToArray($this->contentObject->data['pi_flexform']);
190
191 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexformConfiguration, 'settings');
192 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexformConfiguration, 'persistence');
193 $frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexformConfiguration, 'view');
194
195 $frameworkConfiguration = $this->overrideSwitchableControllerActionsFromFlexform($frameworkConfiguration, $flexformConfiguration);
196 }
197 return $frameworkConfiguration;
198 }
199
200 /**
201 * Parses the FlexForm content recursivly and converts it to an array
202 * The resulting array will be multi-dimensional, as a value "bla.blubb"
203 * results in two levels, and a value "bla.blubb.bla" results in three levels.
204 *
205 * Note: multi-language FlexForms are not supported yet
206 *
207 * @param string $flexFormContent FlexForm xml string
208 * @return array the processed array
209 */
210 protected function convertFlexformContentToArray($flexFormContent) {
211 $settings = array();
212 $languagePointer = 'lDEF';
213 $valuePointer = 'vDEF';
214
215 $flexFormArray = t3lib_div::xml2array($flexFormContent);
216 $flexFormArray = isset($flexFormArray['data']) ? $flexFormArray['data'] : array();
217 foreach(array_values($flexFormArray) as $languages) {
218 if (!is_array($languages[$languagePointer])) {
219 continue;
220 }
221 foreach($languages[$languagePointer] as $valueKey => $valueDefinition) {
222 if (strpos($valueKey, '.') === false) {
223 $settings[$valueKey] = $valueDefinition[$valuePointer];
224 } else {
225 $valueKeyParts = explode('.', $valueKey);
226 $currentNode =& $settings;
227 foreach ($valueKeyParts as $valueKeyPart) {
228 $currentNode =& $currentNode[$valueKeyPart];
229 }
230 $currentNode = $valueDefinition[$valuePointer];
231 }
232 }
233 }
234 return $settings;
235 }
236
237 /**
238 * Merge a configuration into the framework configuration.
239 *
240 * @param array $frameworkConfiguration the framework configuration to merge the data on
241 * @param array $configuration The configuration
242 * @param string $configurationPartName The name of the configuration part which should be merged.
243 * @return array the processed framework configuration
244 */
245 protected function mergeConfigurationIntoFrameworkConfiguration(array $frameworkConfiguration, array $configuration, $configurationPartName) {
246 if (is_array($frameworkConfiguration[$configurationPartName]) && is_array($configuration[$configurationPartName])) {
247 $frameworkConfiguration[$configurationPartName] = t3lib_div::array_merge_recursive_overrule($frameworkConfiguration[$configurationPartName], $configuration[$configurationPartName]);
248 }
249 return $frameworkConfiguration;
250 }
251
252
253 /**
254 * Overrides the switchable controller actions from the flexform.
255 *
256 * @param array $frameworkConfiguration The original framework configuration
257 * @param array $flexformConfiguration The full flexform configuration
258 * @return array the modified framework configuration, if needed
259 * @todo: Check that the controller has been before inside the switchableControllerActions.
260 */
261 protected function overrideSwitchableControllerActionsFromFlexform(array $frameworkConfiguration, array $flexformConfiguration) {
262 if (!isset($flexformConfiguration['switchableControllerActions']) || is_array($flexformConfiguration['switchableControllerActions'])) {
263 return $frameworkConfiguration;
264 }
265
266 // As "," is the flexform field value delimiter, we need to use ";" as in-field delimiter. That's why we need to replace ; by , first.
267 $switchableControllerActionPartsFromFlexform = t3lib_div::trimExplode(',', str_replace(';', ',', $flexformConfiguration['switchableControllerActions']), TRUE);
268
269 $newSwitchableControllerActionsFromFlexform = array();
270 foreach ($switchableControllerActionPartsFromFlexform as $switchableControllerActionPartFromFlexform) {
271 list($controller, $action) = explode('->', $switchableControllerActionPartFromFlexform);
272 if (empty($controller) || empty($action)) {
273 throw new Tx_Extbase_Configuration_Exception_ParseError('Controller or action were empty when overriding switchableControllerActions from flexform.', 1257146403);
274 }
275 $newSwitchableControllerActionsFromFlexform[$controller][] = $action;
276 }
277
278 if (count($newSwitchableControllerActionsFromFlexform)) {
279 $this->overrideSwitchableControllerActions($frameworkConfiguration, $newSwitchableControllerActionsFromFlexform);
280 }
281 return $frameworkConfiguration;
282 }
283 }
284 ?>