[FEATURE] Recursive starting point/storage pid via TypoScript
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Configuration / AbstractConfigurationManager.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Configuration;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2012 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Abstract base class for a general purpose configuration manager
31 */
32 abstract class AbstractConfigurationManager implements \TYPO3\CMS\Core\SingletonInterface {
33
34 /**
35 * Default backend storage PID
36 */
37 const DEFAULT_BACKEND_STORAGE_PID = 0;
38
39 /**
40 * Storage of the raw TypoScript configuration
41 *
42 * @var array
43 */
44 protected $configuration = array();
45
46 /**
47 * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
48 */
49 protected $contentObject;
50
51 /**
52 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
53 */
54 protected $objectManager;
55
56 /**
57 * @var \TYPO3\CMS\Extbase\Service\TypoScriptService
58 */
59 protected $typoScriptService;
60
61 /**
62 * name of the extension this Configuration Manager instance belongs to
63 *
64 * @var string
65 */
66 protected $extensionName;
67
68 /**
69 * name of the plugin this Configuration Manager instance belongs to
70 *
71 * @var string
72 */
73 protected $pluginName;
74
75 /**
76 * 1st level configuration cache
77 *
78 * @var array
79 */
80 protected $configurationCache = array();
81
82 /**
83 * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
84 * @return void
85 */
86 public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) {
87 $this->objectManager = $objectManager;
88 }
89
90 /**
91 * @param \TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService
92 * @return void
93 */
94 public function injectTypoScriptService(\TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService) {
95 $this->typoScriptService = $typoScriptService;
96 }
97
98 /**
99 * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
100 * @return void
101 */
102 public function setContentObject(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject = NULL) {
103 $this->contentObject = $contentObject;
104 }
105
106 /**
107 * @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer|NULL
108 */
109 public function getContentObject() {
110 if ($this->contentObject !== NULL) {
111 return $this->contentObject;
112 }
113 return NULL;
114 }
115
116 /**
117 * Sets the specified raw configuration coming from the outside.
118 * Note that this is a low level method and only makes sense to be used by Extbase internally.
119 *
120 * @param array $configuration The new configuration
121 * @return void
122 */
123 public function setConfiguration(array $configuration = array()) {
124 // reset 1st level cache
125 $this->configurationCache = array();
126 $this->extensionName = isset($configuration['extensionName']) ? $configuration['extensionName'] : NULL;
127 $this->pluginName = isset($configuration['pluginName']) ? $configuration['pluginName'] : NULL;
128 $this->configuration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($configuration);
129 }
130
131 /**
132 * Loads the Extbase Framework configuration.
133 *
134 * The Extbase framework configuration HAS TO be retrieved using this method, as they are come from different places than the normal settings.
135 * Framework configuration is, in contrast to normal settings, needed for the Extbase framework to operate correctly.
136 *
137 * @param string $extensionName if specified, the configuration for the given extension will be returned (plugin.tx_extensionname)
138 * @param string $pluginName if specified, the configuration for the given plugin will be returned (plugin.tx_extensionname_pluginname)
139 * @return array the Extbase framework configuration
140 */
141 public function getConfiguration($extensionName = NULL, $pluginName = NULL) {
142 // 1st level cache
143 $configurationCacheKey = strtolower(($extensionName ?: $this->extensionName) . '_' . ($pluginName ?: $this->pluginName));
144 if (isset($this->configurationCache[$configurationCacheKey])) {
145 return $this->configurationCache[$configurationCacheKey];
146 }
147 $frameworkConfiguration = $this->getExtbaseConfiguration();
148 if (!isset($frameworkConfiguration['persistence']['storagePid'])) {
149 $frameworkConfiguration['persistence']['storagePid'] = $this->getDefaultBackendStoragePid();
150 }
151 // only merge $this->configuration and override switchableControllerActions when retrieving configuration of the current plugin
152 if ($extensionName === NULL || $extensionName === $this->extensionName && $pluginName === $this->pluginName) {
153 $pluginConfiguration = $this->getPluginConfiguration($this->extensionName, $this->pluginName);
154 $pluginConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($pluginConfiguration, $this->configuration);
155 $pluginConfiguration['controllerConfiguration'] = $this->getSwitchableControllerActions($this->extensionName, $this->pluginName);
156 if (isset($this->configuration['switchableControllerActions'])) {
157 $this->overrideSwitchableControllerActions($pluginConfiguration, $this->configuration['switchableControllerActions']);
158 }
159 } else {
160 $pluginConfiguration = $this->getPluginConfiguration($extensionName, $pluginName);
161 $pluginConfiguration['controllerConfiguration'] = $this->getSwitchableControllerActions($extensionName, $pluginName);
162 }
163 $frameworkConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($frameworkConfiguration, $pluginConfiguration);
164 // only load context specific configuration when retrieving configuration of the current plugin
165 if ($extensionName === NULL || $extensionName === $this->extensionName && $pluginName === $this->pluginName) {
166 $frameworkConfiguration = $this->getContextSpecificFrameworkConfiguration($frameworkConfiguration);
167 }
168
169 if (!empty($frameworkConfiguration['persistence']['storagePid'])) {
170 if (is_array($frameworkConfiguration['persistence']['storagePid'])) {
171 /**
172 * We simulate the frontend to enable the use of cObjects in
173 * stdWrap. Than we convert the configuration to normal TypoScript
174 * and apply the stdWrap to the storagePid
175 */
176 if (TYPO3_MODE !== 'FE') {
177 Tx_Extbase_Utility_FrontendSimulator::simulateFrontendEnvironment($this->getContentObject());
178 }
179 $conf = $this->typoScriptService->convertPlainArrayToTypoScriptArray($frameworkConfiguration['persistence']);
180 $frameworkConfiguration['persistence']['storagePid'] = $GLOBALS['TSFE']->cObj->stdWrap($conf['storagePid'], $conf['storagePid.']);
181 if (TYPO3_MODE !== 'FE') {
182 Tx_Extbase_Utility_FrontendSimulator::resetFrontendEnvironment();
183 }
184 }
185
186 if (!empty($frameworkConfiguration['persistence']['recursive'])) {
187 $frameworkConfiguration['persistence']['storagePid'] = $this->getRecursiveStoragePids($frameworkConfiguration['persistence']['storagePid'], (int) $frameworkConfiguration['persistence']['recursive']);
188 }
189 }
190 // 1st level cache
191 $this->configurationCache[$configurationCacheKey] = $frameworkConfiguration;
192 return $frameworkConfiguration;
193 }
194
195 /**
196 * Returns the TypoScript configuration found in config.tx_extbase
197 *
198 * @return array
199 */
200 protected function getExtbaseConfiguration() {
201 $setup = $this->getTypoScriptSetup();
202 $extbaseConfiguration = array();
203 if (isset($setup['config.']['tx_extbase.'])) {
204 $extbaseConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['config.']['tx_extbase.']);
205 }
206 return $extbaseConfiguration;
207 }
208
209 /**
210 * Returns the default backend storage pid
211 *
212 * @return string
213 */
214 public function getDefaultBackendStoragePid() {
215 return self::DEFAULT_BACKEND_STORAGE_PID;
216 }
217
218 /**
219 * @param array &$frameworkConfiguration
220 * @param array $switchableControllerActions
221 * @return void
222 */
223 protected function overrideSwitchableControllerActions(array &$frameworkConfiguration, array $switchableControllerActions) {
224 $overriddenSwitchableControllerActions = array();
225 foreach ($switchableControllerActions as $controllerName => $actions) {
226 if (!isset($frameworkConfiguration['controllerConfiguration'][$controllerName])) {
227 continue;
228 }
229 $overriddenSwitchableControllerActions[$controllerName] = array('actions' => $actions);
230 $nonCacheableActions = $frameworkConfiguration['controllerConfiguration'][$controllerName]['nonCacheableActions'];
231 if (!is_array($nonCacheableActions)) {
232 // There are no non-cacheable actions, thus we can directly continue
233 // with the next controller name.
234 continue;
235 }
236 $overriddenNonCacheableActions = array_intersect($nonCacheableActions, $actions);
237 if (!empty($overriddenNonCacheableActions)) {
238 $overriddenSwitchableControllerActions[$controllerName]['nonCacheableActions'] = $overriddenNonCacheableActions;
239 }
240 }
241 $frameworkConfiguration['controllerConfiguration'] = $overriddenSwitchableControllerActions;
242 }
243
244 /**
245 * The context specific configuration returned by this method
246 * will override the framework configuration which was
247 * obtained from TypoScript. This can be used f.e. to override the storagePid
248 * with the value set inside the Plugin Instance.
249 *
250 * WARNING: Make sure this method ALWAYS returns an array!
251 *
252 * @param array $frameworkConfiguration The framework configuration until now
253 * @return array context specific configuration which will override the configuration obtained by TypoScript
254 */
255 abstract protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration);
256
257 /**
258 * Returns TypoScript Setup array from current Environment.
259 *
260 * @return array the TypoScript setup
261 */
262 abstract public function getTypoScriptSetup();
263
264 /**
265 * Returns the TypoScript configuration found in plugin.tx_yourextension_yourplugin / module.tx_yourextension_yourmodule
266 * merged with the global configuration of your extension from plugin.tx_yourextension / module.tx_yourextension
267 *
268 * @param string $extensionName
269 * @param string $pluginName in FE mode this is the specified plugin name, in BE mode this is the full module signature
270 * @return array
271 */
272 abstract protected function getPluginConfiguration($extensionName, $pluginName = NULL);
273
274 /**
275 * Returns the configured controller/action pairs of the specified plugin/module in the format
276 * array(
277 * 'Controller1' => array('action1', 'action2'),
278 * 'Controller2' => array('action3', 'action4')
279 * )
280 *
281 * @param string $extensionName
282 * @param string $pluginName in FE mode this is the specified plugin name, in BE mode this is the full module signature
283 * @return array
284 */
285 abstract protected function getSwitchableControllerActions($extensionName, $pluginName);
286
287 /**
288 * The implementation of the methods to return a list of storagePid that are below a certain
289 * storage pid.
290 *
291 * @param string $storagePid Storage PID to start at; multiple PIDs possible as comma-separated list
292 * @param integer $recursionDepth Maximum number of levels to search, 0 to disable recursive lookup
293 * @return string storage PIDs
294 */
295 abstract protected function getRecursiveStoragePids($storagePid, $recursionDepth = 0);
296
297 }
298
299 ?>