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