[!!!][TASK] Rewrite install tool
[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-2013 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 * - EXT:core/Configuration/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 {
40
41 /**
42 * @var string Path to default TYPO3_CONF_VARS file, relative to PATH_site
43 */
44 protected $defaultConfigurationFile = 'typo3/sysext/core/Configuration/DefaultConfiguration.php';
45
46 /**
47 * @var string Path to local overload TYPO3_CONF_VARS file, relative to PATH_site
48 */
49 protected $localConfigurationFile = 'typo3conf/LocalConfiguration.php';
50
51 /**
52 * @var string Path to additional local file, relative to PATH_site
53 */
54 protected $additionalConfigurationFile = 'typo3conf/AdditionalConfiguration.php';
55
56 /**
57 * @var string Path to factory configuration file used during installation as LocalConfiguration boilerplate
58 */
59 protected $factoryConfigurationFile = 'typo3/sysext/core/Configuration/FactoryConfiguration.php';
60
61 /**
62 * @var string Path to possible additional factory configuration file delivered by packages
63 */
64 protected $additionalFactoryConfigurationFile = 'typo3conf/AdditionalFactoryConfiguration.php';
65
66 /**
67 * @var string Absolute path to typo3conf directory
68 */
69 protected $pathTypo3Conf = PATH_typo3conf;
70
71 /**
72 * Writing to these configuration pathes is always allowed,
73 * even if the requested sub path does not exist yet.
74 *
75 * @var array
76 */
77 protected $whiteListedLocalConfigurationPaths = array(
78 'EXT/extConf',
79 'EXTCONF',
80 'INSTALL/wizardDone',
81 'DB'
82 );
83
84 /**
85 * Return default configuration array
86 *
87 * @return array
88 */
89 public function getDefaultConfiguration() {
90 return require $this->getDefaultConfigurationFileLocation();
91 }
92
93 /**
94 * Get the file location of the default configuration file,
95 * currently the path and filename.
96 *
97 * @return string
98 * @access private
99 */
100 public function getDefaultConfigurationFileLocation() {
101 return PATH_site . $this->defaultConfigurationFile;
102 }
103
104 /**
105 * Return local configuration array typo3conf/LocalConfiguration.php
106 *
107 * @return array Content array of local configuration file
108 */
109 public function getLocalConfiguration() {
110 return require $this->getLocalConfigurationFileLocation();
111 }
112
113 /**
114 * Get the file location of the local configuration file,
115 * currently the path and filename.
116 *
117 * @return string
118 * @access private
119 */
120 public function getLocalConfigurationFileLocation() {
121 return PATH_site . $this->localConfigurationFile;
122 }
123
124 /**
125 * Get the file location of the additional configuration file,
126 * currently the path and filename.
127 *
128 * @return string
129 * @access private
130 */
131 public function getAdditionalConfigurationFileLocation() {
132 return PATH_site . $this->additionalConfigurationFile;
133 }
134
135 /**
136 * Get absolute file location of factory configuration file
137 *
138 * @return string
139 */
140 protected function getFactoryConfigurationFileLocation() {
141 return PATH_site . $this->factoryConfigurationFile;
142 }
143
144 /**
145 * Get absolute file location of factory configuration file
146 *
147 * @return string
148 */
149 protected function getAdditionalFactoryConfigurationFileLocation() {
150 return PATH_site . $this->additionalFactoryConfigurationFile;
151 }
152
153 /**
154 * Override local configuration with new values.
155 *
156 * @param array $configurationToMerge Override configuration array
157 * @return void
158 */
159 public function updateLocalConfiguration(array $configurationToMerge) {
160 $newLocalConfiguration = Utility\GeneralUtility::array_merge_recursive_overrule(
161 $this->getLocalConfiguration(),
162 $configurationToMerge
163 );
164 $this->writeLocalConfiguration($newLocalConfiguration);
165 }
166
167 /**
168 * Get a value at given path from default configuration
169 *
170 * @param string $path Path to search for
171 * @return mixed Value at path
172 */
173 public function getDefaultConfigurationValueByPath($path) {
174 return Utility\ArrayUtility::getValueByPath($this->getDefaultConfiguration(), $path);
175 }
176
177 /**
178 * Get a value at given path from local configuration
179 *
180 * @param string $path Path to search for
181 * @return mixed Value at path
182 */
183 public function getLocalConfigurationValueByPath($path) {
184 return Utility\ArrayUtility::getValueByPath($this->getLocalConfiguration(), $path);
185 }
186
187 /**
188 * Get a value from configuration, this is default configuration
189 * merged with local configuration
190 *
191 * @param string $path Path to search for
192 * @return mixed
193 */
194 public function getConfigurationValueByPath($path) {
195 return Utility\ArrayUtility::getValueByPath(
196 Utility\GeneralUtility::array_merge_recursive_overrule(
197 $this->getDefaultConfiguration(), $this->getLocalConfiguration()
198 ),
199 $path
200 );
201 }
202
203 /**
204 * Update a given path in local configuration to a new value.
205 *
206 * @param string $path Path to update
207 * @param mixed $value Value to set
208 * @return boolean TRUE on success
209 */
210 public function setLocalConfigurationValueByPath($path, $value) {
211 $result = FALSE;
212 if ($this->isValidLocalConfigurationPath($path)) {
213 $localConfiguration = $this->getLocalConfiguration();
214 $localConfiguration = Utility\ArrayUtility::setValueByPath($localConfiguration, $path, $value);
215 $result = $this->writeLocalConfiguration($localConfiguration);
216 }
217 return $result;
218 }
219
220 /**
221 * Update / set a list of path and value pairs in local configuration file
222 *
223 * @param array $pairs Key is path, value is value to set
224 * @return boolean TRUE on success
225 */
226 public function setLocalConfigurationValuesByPathValuePairs(array $pairs) {
227 $localConfiguration = $this->getLocalConfiguration();
228 foreach ($pairs as $path => $value) {
229 if ($this->isValidLocalConfigurationPath($path)) {
230 $localConfiguration = Utility\ArrayUtility::setValueByPath($localConfiguration, $path, $value);
231 }
232 }
233 return $this->writeLocalConfiguration($localConfiguration);
234 }
235
236 /**
237 * Checks if the configuration can be written.
238 *
239 * @return boolean
240 * @access private
241 */
242 public function canWriteConfiguration() {
243 $result = TRUE;
244 if (!@is_writable($this->pathTypo3Conf)) {
245 $result = FALSE;
246 }
247 if (
248 file_exists($this->getLocalConfigurationFileLocation())
249 && !@is_writable($this->getLocalConfigurationFileLocation())
250 ) {
251 $result = FALSE;
252 }
253 return $result;
254 }
255
256 /**
257 * Reads the configuration array and exports it to the global variable
258 *
259 * @access private
260 * @throws \UnexpectedValueException
261 * @return void
262 */
263 public function exportConfiguration() {
264 if (@is_file($this->getLocalConfigurationFileLocation())) {
265 $localConfiguration = $this->getLocalConfiguration();
266 if (is_array($localConfiguration)) {
267 $GLOBALS['TYPO3_CONF_VARS'] = Utility\GeneralUtility::array_merge_recursive_overrule($this->getDefaultConfiguration(), $localConfiguration);
268 } else {
269 throw new \UnexpectedValueException('LocalConfiguration invalid.', 1349272276);
270 }
271 if (@is_file($this->getAdditionalConfigurationFileLocation())) {
272 require $this->getAdditionalConfigurationFileLocation();
273 }
274 } else {
275 // No LocalConfiguration (yet), load DefaultConfiguration only
276 $GLOBALS['TYPO3_CONF_VARS'] = $this->getDefaultConfiguration();
277 }
278 }
279
280 /**
281 * Write local configuration array to typo3conf/LocalConfiguration.php
282 *
283 * @param array $configuration The local configuration to be written
284 * @throws \RuntimeException
285 * @return boolean TRUE on success
286 * @access private
287 */
288 public function writeLocalConfiguration(array $configuration) {
289 $localConfigurationFile = $this->getLocalConfigurationFileLocation();
290 if (!$this->canWriteConfiguration()) {
291 throw new \RuntimeException(
292 $localConfigurationFile . ' is not writable.', 1346323822
293 );
294 }
295 $configuration = Utility\ArrayUtility::sortByKeyRecursive($configuration);
296 $result = Utility\GeneralUtility::writeFile(
297 $localConfigurationFile,
298 '<?php' . LF .
299 'return ' .
300 Utility\ArrayUtility::arrayExport(
301 Utility\ArrayUtility::renumberKeysToAvoidLeapsIfKeysAreAllNumeric($configuration)
302 ) .
303 ';' . LF .
304 '?>',
305 TRUE
306 );
307 return $result === FALSE ? FALSE : TRUE;
308 }
309
310 /**
311 * Write additional configuration array to typo3conf/AdditionalConfiguration.php
312 *
313 * @param array $additionalConfigurationLines The configuration lines to be written
314 * @throws \RuntimeException
315 * @return boolean TRUE on success
316 * @access private
317 */
318 public function writeAdditionalConfiguration(array $additionalConfigurationLines) {
319 $result = Utility\GeneralUtility::writeFile(
320 PATH_site . $this->additionalConfigurationFile,
321 '<?php' . LF .
322 implode(LF, $additionalConfigurationLines) . LF .
323 '?>'
324 );
325 return $result === FALSE ? FALSE : TRUE;
326 }
327
328 /**
329 * Uses FactoryConfiguration file and a possible AdditionalFactoryConfiguration
330 * file in typo3conf to create a basic LocalConfiguration.php. This is used
331 * by the install tool in an early step.
332 *
333 * @throws \RuntimeException
334 * @return void
335 * @access private
336 */
337 public function createLocalConfigurationFromFactoryConfiguration() {
338 if (file_exists($this->getLocalConfigurationFileLocation())) {
339 throw new \RuntimeException(
340 'LocalConfiguration.php exists already',
341 1364836026
342 );
343 }
344 $localConfigurationArray = require $this->getFactoryConfigurationFileLocation();
345 $additionalFactoryConfigurationFileLocation = $this->getAdditionalFactoryConfigurationFileLocation();
346 if (file_exists($additionalFactoryConfigurationFileLocation)) {
347 $additionalFactoryConfigurationArray = require $additionalFactoryConfigurationFileLocation;
348 $localConfigurationArray = Utility\GeneralUtility::array_merge_recursive_overrule(
349 $localConfigurationArray,
350 $additionalFactoryConfigurationArray
351 );
352 }
353 $this->writeLocalConfiguration($localConfigurationArray);
354 }
355
356 /**
357 * Check if access / write to given path in local configuration is allowed.
358 *
359 * @param string $path Path to search for
360 * @return boolean TRUE if access is allowed
361 */
362 protected function isValidLocalConfigurationPath($path) {
363 // Early return for white listed paths
364 foreach ($this->whiteListedLocalConfigurationPaths as $whiteListedPath) {
365 if (Utility\GeneralUtility::isFirstPartOfStr($path, $whiteListedPath)) {
366 return TRUE;
367 }
368 }
369 return Utility\ArrayUtility::isValidPath($this->getDefaultConfiguration(), $path);
370 }
371
372 }
373
374
375 ?>