‪TYPO3CMS  10.4
ConfigurationManager.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
23 
39 class ConfigurationManager
40 {
44  protected $defaultConfigurationFile = 'core/Configuration/DefaultConfiguration.php';
45 
49  protected $defaultConfigurationDescriptionFile = 'core/Configuration/DefaultConfigurationDescription.yaml';
50 
54  protected $localConfigurationFile = 'LocalConfiguration.php';
55 
59  protected $additionalConfigurationFile = 'AdditionalConfiguration.php';
60 
64  protected $factoryConfigurationFile = 'core/Configuration/FactoryConfiguration.php';
65 
69  protected $additionalFactoryConfigurationFile = 'AdditionalFactoryConfiguration.php';
70 
77  protected $whiteListedLocalConfigurationPaths = [
78  'EXTCONF',
79  'DB',
80  'SYS/caching/cacheConfigurations',
81  'SYS/session',
82  'EXTENSIONS',
83  ];
84 
90  public function getDefaultConfiguration()
91  {
92  return require $this->getDefaultConfigurationFileLocation();
93  }
94 
102  public function getDefaultConfigurationFileLocation()
103  {
104  return ‪Environment::getFrameworkBasePath() . '/' . $this->defaultConfigurationFile;
105  }
106 
114  public function getDefaultConfigurationDescriptionFileLocation()
115  {
116  return ‪Environment::getFrameworkBasePath() . '/' . $this->defaultConfigurationDescriptionFile;
117  }
118 
124  public function getLocalConfiguration()
125  {
126  return require $this->getLocalConfigurationFileLocation();
127  }
128 
136  public function getLocalConfigurationFileLocation()
137  {
138  return ‪Environment::getLegacyConfigPath() . '/' . $this->localConfigurationFile;
139  }
140 
146  public function getMergedLocalConfiguration(): array
147  {
148  $localConfiguration = $this->getDefaultConfiguration();
149  ‪ArrayUtility::mergeRecursiveWithOverrule($localConfiguration, $this->getLocalConfiguration());
150  return $localConfiguration;
151  }
152 
160  public function getAdditionalConfigurationFileLocation()
161  {
162  return ‪Environment::getLegacyConfigPath() . '/' . $this->additionalConfigurationFile;
163  }
164 
170  protected function getFactoryConfigurationFileLocation()
171  {
172  return ‪Environment::getFrameworkBasePath() . '/' . $this->factoryConfigurationFile;
173  }
174 
180  protected function getAdditionalFactoryConfigurationFileLocation()
181  {
182  return ‪Environment::getLegacyConfigPath() . '/' . $this->additionalFactoryConfigurationFile;
183  }
184 
190  public function updateLocalConfiguration(array $configurationToMerge)
191  {
192  $newLocalConfiguration = $this->getLocalConfiguration();
193  ‪ArrayUtility::mergeRecursiveWithOverrule($newLocalConfiguration, $configurationToMerge);
194  $this->writeLocalConfiguration($newLocalConfiguration);
195  }
196 
203  public function getDefaultConfigurationValueByPath($path)
204  {
205  return ‪ArrayUtility::getValueByPath($this->getDefaultConfiguration(), $path);
206  }
207 
214  public function getLocalConfigurationValueByPath($path)
215  {
216  return ‪ArrayUtility::getValueByPath($this->getLocalConfiguration(), $path);
217  }
218 
226  public function getConfigurationValueByPath($path)
227  {
228  $defaultConfiguration = $this->getDefaultConfiguration();
229  ‪ArrayUtility::mergeRecursiveWithOverrule($defaultConfiguration, $this->getLocalConfiguration());
230  return ‪ArrayUtility::getValueByPath($defaultConfiguration, $path);
231  }
232 
240  public function setLocalConfigurationValueByPath($path, $value)
241  {
242  $result = false;
243  if ($this->isValidLocalConfigurationPath($path)) {
244  $localConfiguration = $this->getLocalConfiguration();
245  $localConfiguration = ‪ArrayUtility::setValueByPath($localConfiguration, $path, $value);
246  $result = $this->writeLocalConfiguration($localConfiguration);
247  }
248  return $result;
249  }
250 
257  public function setLocalConfigurationValuesByPathValuePairs(array $pairs)
258  {
259  $localConfiguration = $this->getLocalConfiguration();
260  foreach ($pairs as $path => $value) {
261  if ($this->isValidLocalConfigurationPath($path)) {
262  $localConfiguration = ‪ArrayUtility::setValueByPath($localConfiguration, $path, $value);
263  }
264  }
265  return $this->writeLocalConfiguration($localConfiguration);
266  }
267 
274  public function removeLocalConfigurationKeysByPath(array $keys)
275  {
276  $result = false;
277  $localConfiguration = $this->getLocalConfiguration();
278  foreach ($keys as $path) {
279  // Remove key if path is within LocalConfiguration
280  if (‪ArrayUtility::isValidPath($localConfiguration, $path)) {
281  $result = true;
282  $localConfiguration = ‪ArrayUtility::removeByPath($localConfiguration, $path);
283  }
284  }
285  if ($result) {
286  $this->writeLocalConfiguration($localConfiguration);
287  }
288  return $result;
289  }
290 
298  public function enableFeature(string $featureName): bool
299  {
300  return $this->setLocalConfigurationValueByPath('SYS/features/' . $featureName, true);
301  }
302 
310  public function disableFeature(string $featureName): bool
311  {
312  return $this->setLocalConfigurationValueByPath('SYS/features/' . $featureName, false);
313  }
314 
321  public function canWriteConfiguration()
322  {
323  $fileLocation = $this->getLocalConfigurationFileLocation();
324  return @is_writable(file_exists($fileLocation) ? $fileLocation : ‪Environment::getLegacyConfigPath() . '/');
325  }
326 
333  public function exportConfiguration()
334  {
335  if (@is_file($this->getLocalConfigurationFileLocation())) {
336  $localConfiguration = $this->getLocalConfiguration();
337  if (is_array($localConfiguration)) {
338  $defaultConfiguration = $this->getDefaultConfiguration();
339  ‪ArrayUtility::mergeRecursiveWithOverrule($defaultConfiguration, $localConfiguration);
340  ‪$GLOBALS['TYPO3_CONF_VARS'] = $defaultConfiguration;
341  } else {
342  throw new \UnexpectedValueException('LocalConfiguration invalid.', 1349272276);
343  }
344  } else {
345  // No LocalConfiguration (yet), load DefaultConfiguration
346  ‪$GLOBALS['TYPO3_CONF_VARS'] = $this->getDefaultConfiguration();
347  }
348 
349  // Load AdditionalConfiguration
350  if (@is_file($this->getAdditionalConfigurationFileLocation())) {
351  require $this->getAdditionalConfigurationFileLocation();
352  }
353  }
354 
363  public function writeLocalConfiguration(array $configuration)
364  {
365  $localConfigurationFile = $this->getLocalConfigurationFileLocation();
366  if (!$this->canWriteConfiguration()) {
367  throw new \RuntimeException(
368  $localConfigurationFile . ' is not writable.',
369  1346323822
370  );
371  }
372  $configuration = ‪ArrayUtility::sortByKeyRecursive($configuration);
374  $localConfigurationFile,
375  "<?php\n" .
376  'return ' .
377  ‪ArrayUtility::arrayExport($configuration) .
378  ";\n",
379  true
380  );
381 
382  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($localConfigurationFile);
383 
384  return $result;
385  }
386 
395  public function writeAdditionalConfiguration(array $additionalConfigurationLines)
396  {
398  $this->getAdditionalConfigurationFileLocation(),
399  "<?php\n" . implode("\n", $additionalConfigurationLines) . "\n"
400  );
401  }
402 
411  public function createLocalConfigurationFromFactoryConfiguration()
412  {
413  if (file_exists($this->getLocalConfigurationFileLocation())) {
414  throw new \RuntimeException(
415  'LocalConfiguration.php exists already',
416  1364836026
417  );
418  }
419  $localConfigurationArray = require $this->getFactoryConfigurationFileLocation();
420  $additionalFactoryConfigurationFileLocation = $this->getAdditionalFactoryConfigurationFileLocation();
421  if (file_exists($additionalFactoryConfigurationFileLocation)) {
422  $additionalFactoryConfigurationArray = require $additionalFactoryConfigurationFileLocation;
424  $localConfigurationArray,
425  $additionalFactoryConfigurationArray
426  );
427  }
428  $randomKey = GeneralUtility::makeInstance(Random::class)->generateRandomHexString(96);
429  $localConfigurationArray['SYS']['encryptionKey'] = $randomKey;
430 
431  $this->writeLocalConfiguration($localConfigurationArray);
432  }
433 
440  protected function isValidLocalConfigurationPath($path)
441  {
442  // Early return for white listed paths
443  foreach ($this->whiteListedLocalConfigurationPaths as $whiteListedPath) {
444  if (GeneralUtility::isFirstPartOfStr($path, $whiteListedPath)) {
445  return true;
446  }
447  }
448  return ‪ArrayUtility::isValidPath($this->getDefaultConfiguration(), $path);
449  }
450 }
‪TYPO3\CMS\Core\Utility\ArrayUtility\isValidPath
‪static bool isValidPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:144
‪TYPO3\CMS\Core\Utility\ArrayUtility\sortByKeyRecursive
‪static array sortByKeyRecursive(array $array)
Definition: ArrayUtility.php:354
‪TYPO3\CMS\Core\Utility\ArrayUtility\arrayExport
‪static string arrayExport(array $array=[], $level=0)
Definition: ArrayUtility.php:402
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Core\Environment\getFrameworkBasePath
‪static string getFrameworkBasePath()
Definition: Environment.php:261
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:180
‪TYPO3\CMS\Core\Utility\ArrayUtility\removeByPath
‪static array removeByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:316
‪TYPO3\CMS\Core\Service\OpcodeCacheService
Definition: OpcodeCacheService.php:25
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, $path, $value, $delimiter='/')
Definition: ArrayUtility.php:272
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Configuration
Definition: ConfigurationManager.php:16
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Crypto\Random
Definition: Random.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1836
‪TYPO3\CMS\Core\Core\Environment\getLegacyConfigPath
‪static string getLegacyConfigPath()
Definition: Environment.php:282