1dd14c384c7972f3765b6e288ad4633c7fed08d6
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Configuration / ConfigurationManager.php
1 <?php
2 namespace TYPO3\CMS\Core\Configuration;
3 use TYPO3\CMS\Core\Utility;
4
5 /***************************************************************
6 * Copyright notice
7 *
8 * (c) 2012 Helge Funk <helge.funk@e-net.info>
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 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Handle loading and writing of global and local (instance specific)
29 * configuration.
30 *
31 * This class handles the access to the files
32 * - t3lib/stddb/DefaultConfiguration.php (default TYPO3_CONF_VARS)
33 * - typo3conf/LocalConfiguration.php (overrides of TYPO3_CONF_VARS)
34 * - typo3conf/AdditionalConfiguration.php (optional additional local code blocks)
35 * - typo3conf/localconf.php (legacy configuration file)
36 *
37 * @author Helge Funk <helge.funk@e-net.info>
38 */
39 class ConfigurationManager implements \TYPO3\CMS\Core\SingletonInterface {
40
41 /**
42 * Path to default TYPO3_CONF_VARS file, relative to PATH_site
43 */
44 const DEFAULT_CONFIGURATION_FILE = 't3lib/stddb/DefaultConfiguration.php';
45 /**
46 * Path to local overload TYPO3_CONF_VARS file, relative to PATH_site
47 */
48 const LOCAL_CONFIGURATION_FILE = 'typo3conf/LocalConfiguration.php';
49 /**
50 * Path to additional local file, relative to PATH_site
51 */
52 const ADDITIONAL_CONFIGURATION_FILE = 'typo3conf/AdditionalConfiguration.php';
53 /**
54 * Path to legacy localconf.php file, relative to PATH_site
55 */
56 const LOCALCONF_FILE = 'typo3conf/localconf.php';
57 /**
58 * Writing to these configuration pathes is always allowed,
59 * even if the requested sub path does not exist yet.
60 *
61 * @var array
62 */
63 protected $whiteListedLocalConfigurationPaths = array(
64 'EXT/extConf',
65 'EXTCONF',
66 'INSTALL/wizardDone',
67 'DB'
68 );
69
70 /**
71 * Return default configuration array t3lib/stddb/DefaultConfiguration.php
72 *
73 * @return array
74 */
75 public function getDefaultConfiguration() {
76 return require $this->getDefaultConfigurationFileResource();
77 }
78
79 /**
80 * Get the file resource of the default configuration file,
81 * currently the path and filename.
82 *
83 * @return string
84 * @access private
85 */
86 public function getDefaultConfigurationFileResource() {
87 return PATH_site . self::DEFAULT_CONFIGURATION_FILE;
88 }
89
90 /**
91 * Return local configuration array typo3conf/LocalConfiguration.php
92 *
93 * @return array Content array of local configuration file
94 */
95 public function getLocalConfiguration() {
96 return require $this->getLocalConfigurationFileResource();
97 }
98
99 /**
100 * Get the file resource of the local configuration file,
101 * currently the path and filename.
102 *
103 * @return string
104 * @access private
105 */
106 public function getLocalConfigurationFileResource() {
107 return PATH_site . self::LOCAL_CONFIGURATION_FILE;
108 }
109
110 /**
111 * Get the file resource of the aditional configuration file,
112 * currently the path and filename.
113 *
114 * @return string
115 * @access private
116 */
117 public function getAdditionalConfigurationFileResource() {
118 return PATH_site . self::ADDITIONAL_CONFIGURATION_FILE;
119 }
120
121 /**
122 * Override local configuration with new values.
123 *
124 * @param array $configurationToMerge Override configuration array
125 * @return void
126 */
127 public function updateLocalConfiguration(array $configurationToMerge) {
128 $newLocalConfiguration = Utility\GeneralUtility::array_merge_recursive_overrule($this->getLocalConfiguration(), $configurationToMerge);
129 $this->writeLocalConfiguration($newLocalConfiguration);
130 }
131
132 /**
133 * Get a value at given path from default configuration
134 *
135 * @param string $path Path to search for
136 * @return mixed Value at path
137 */
138 public function getDefaultConfigurationValueByPath($path) {
139 return Utility\ArrayUtility::getValueByPath($this->getDefaultConfiguration(), $path);
140 }
141
142 /**
143 * Get a value at given path from local configuration
144 *
145 * @param string $path Path to search for
146 * @return mixed Value at path
147 */
148 public function getLocalConfigurationValueByPath($path) {
149 return Utility\ArrayUtility::getValueByPath($this->getLocalConfiguration(), $path);
150 }
151
152 /**
153 * Get a value from configuration, this is default configuration
154 * merged with local configuration
155 *
156 * @param string $path Path to search for
157 * @return mixed
158 */
159 public function getConfigurationValueByPath($path) {
160 return Utility\ArrayUtility::getValueByPath(Utility\GeneralUtility::array_merge_recursive_overrule($this->getDefaultConfiguration(), $this->getLocalConfiguration()), $path);
161 }
162
163 /**
164 * Update a given path in local configuration to a new value.
165 *
166 * @param string $path Path to update
167 * @param mixed $value Value to set
168 * @return boolean TRUE on success
169 */
170 public function setLocalConfigurationValueByPath($path, $value) {
171 $result = FALSE;
172 if ($this->isValidLocalConfigurationPath($path)) {
173 $localConfiguration = $this->getLocalConfiguration();
174 $localConfiguration = Utility\ArrayUtility::setValueByPath($localConfiguration, $path, $value);
175 $result = $this->writeLocalConfiguration($localConfiguration);
176 }
177 return $result;
178 }
179
180 /**
181 * Update / set a list of path and value pairs in local configuration file
182 *
183 * @param array $pairs Key is path, value is value to set
184 * @return boolean TRUE on success
185 */
186 public function setLocalConfigurationValuesByPathValuePairs(array $pairs) {
187 $localConfiguration = $this->getLocalConfiguration();
188 foreach ($pairs as $path => $value) {
189 if ($this->isValidLocalConfigurationPath($path)) {
190 $localConfiguration = Utility\ArrayUtility::setValueByPath($localConfiguration, $path, $value);
191 }
192 }
193 return $this->writeLocalConfiguration($localConfiguration);
194 }
195
196 /**
197 * Checks if the configuration can be written
198 *
199 * @return boolean
200 * @access private
201 */
202 public function canWriteConfiguration() {
203 $result = TRUE;
204 if (!@is_writable(PATH_typo3conf)) {
205 $result = FALSE;
206 }
207 if (!@is_writable(($this->getLocalConfigurationFileResource())) && !@is_writable((PATH_site . self::LOCALCONF_FILE))) {
208 $result = FALSE;
209 }
210 return $result;
211 }
212
213 /**
214 * Reads the configuration array and exports it to the global variable
215 *
216 * @access private
217 * @return void
218 */
219 public function exportConfiguration() {
220 if (@is_file(($this->getLocalConfigurationFileResource()))) {
221 $localConfiguration = $this->getLocalConfiguration();
222 if (is_array($localConfiguration)) {
223 $GLOBALS['TYPO3_CONF_VARS'] = Utility\GeneralUtility::array_merge_recursive_overrule($this->getDefaultConfiguration(), $localConfiguration);
224 } else {
225 throw new \UnexpectedValueException('LocalConfiguration invalid.', 1349272276);
226 }
227 if (@is_file((PATH_site . self::ADDITIONAL_CONFIGURATION_FILE))) {
228 require PATH_site . self::ADDITIONAL_CONFIGURATION_FILE;
229 }
230 } elseif (@is_file((PATH_site . self::LOCALCONF_FILE))) {
231 $GLOBALS['TYPO3_CONF_VARS'] = $this->getDefaultConfiguration();
232 // Legacy localconf.php handling
233 // @deprecated: Can be removed if old localconf.php is not supported anymore
234 global $TYPO3_CONF_VARS, $typo_db, $typo_db_username, $typo_db_password, $typo_db_host, $typo_db_extTableDef_script;
235 require PATH_site . self::LOCALCONF_FILE;
236 // If the localconf.php was not upgraded to LocalConfiguration.php, the default extListArray
237 // from t3lib/stddb/DefaultConfiguration.php is still set. In this case we just unset
238 // this key here, so t3lib_extMgm::getLoadedExtensionListArray() falls back to use extList string
239 // @deprecated: This case can be removed later if localconf.php is not supported anymore
240 unset($TYPO3_CONF_VARS['EXT']['extListArray']);
241 // Write the old globals into the new place in the configuration array
242 $GLOBALS['TYPO3_CONF_VARS']['DB'] = array();
243 $GLOBALS['TYPO3_CONF_VARS']['DB']['database'] = $typo_db;
244 $GLOBALS['TYPO3_CONF_VARS']['DB']['username'] = $typo_db_username;
245 $GLOBALS['TYPO3_CONF_VARS']['DB']['password'] = $typo_db_password;
246 $GLOBALS['TYPO3_CONF_VARS']['DB']['host'] = $typo_db_host;
247 $GLOBALS['TYPO3_CONF_VARS']['DB']['extTablesDefinitionScript'] = $typo_db_extTableDef_script;
248 unset($GLOBALS['typo_db']);
249 unset($GLOBALS['typo_db_username']);
250 unset($GLOBALS['typo_db_password']);
251 unset($GLOBALS['typo_db_host']);
252 unset($GLOBALS['typo_db_extTableDef_script']);
253 } else {
254 throw new \RuntimeException('Neither ' . self::LOCAL_CONFIGURATION_FILE . ' (recommended) nor ' . self::LOCALCONF_FILE . ' (obsolete) could be found!', 1349272337);
255 }
256 }
257
258 /**
259 * Write local configuration array to typo3conf/LocalConfiguration.php
260 *
261 * @param array $configuration The local configuration to be written
262 * @throws \RuntimeException
263 * @return boolean TRUE on success
264 * @access private
265 */
266 public function writeLocalConfiguration(array $configuration) {
267 $localConfigurationFile = $this->getLocalConfigurationFileResource();
268 if (!@is_file($localConfigurationFile) || !@is_writable($localConfigurationFile)) {
269 throw new \RuntimeException($localConfigurationFile . ' does not exist or is not writable.', 1346323822);
270 }
271 $configuration = Utility\ArrayUtility::sortByKeyRecursive($configuration);
272 $result = Utility\GeneralUtility::writeFile(
273 $localConfigurationFile,
274 '<?php' . LF . 'return ' . Utility\ArrayUtility::arrayExport($configuration) . ';' . LF . '?>'
275 );
276 return $result === FALSE ? FALSE : TRUE;
277 }
278
279 /**
280 * Write additional configuration array to typo3conf/AdditionalConfiguration.php
281 *
282 * @param array $additionalConfigurationLines The configuration lines to be written
283 * @throws \RuntimeException
284 * @return boolean TRUE on success
285 * @access private
286 */
287 public function writeAdditionalConfiguration(array $additionalConfigurationLines) {
288 $result = Utility\GeneralUtility::writeFile(PATH_site . self::ADDITIONAL_CONFIGURATION_FILE, '<?php' . LF . implode(LF, $additionalConfigurationLines) . LF . '?>');
289 return $result === FALSE ? FALSE : TRUE;
290 }
291
292 /**
293 * Check if access / write to given path in local configuration is allowed.
294 *
295 * @param string $path Path to search for
296 * @return boolean TRUE if access is allowed
297 */
298 protected function isValidLocalConfigurationPath($path) {
299 // Early return for white listed paths
300 foreach ($this->whiteListedLocalConfigurationPaths as $whiteListedPath) {
301 if (Utility\GeneralUtility::isFirstPartOfStr($path, $whiteListedPath)) {
302 return TRUE;
303 }
304 }
305 return Utility\ArrayUtility::isValidPath($this->getDefaultConfiguration(), $path);
306 }
307
308 }
309
310
311 ?>