‪TYPO3CMS  11.5
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 = __DIR__ . '/../../Configuration/DefaultConfiguration.php';
45 
49  protected $defaultConfigurationDescriptionFile = 'EXT:core/Configuration/DefaultConfigurationDescription.yaml';
50 
54  protected $localConfigurationFile = 'LocalConfiguration.php';
55 
59  protected $additionalConfigurationFile = 'AdditionalConfiguration.php';
60 
64  protected $factoryConfigurationFile = __DIR__ . '/../../Configuration/FactoryConfiguration.php';
65 
69  protected $additionalFactoryConfigurationFile = 'AdditionalFactoryConfiguration.php';
70 
77  protected $whiteListedLocalConfigurationPaths = [
78  'EXTCONF',
79  'DB',
80  'SYS/caching/cacheConfigurations',
81  'SYS/encryptionKey',
82  'SYS/session',
83  'EXTENSIONS',
84  ];
85 
91  public function getDefaultConfiguration()
92  {
93  return require $this->getDefaultConfigurationFileLocation();
94  }
95 
103  public function getDefaultConfigurationFileLocation()
104  {
105  return $this->defaultConfigurationFile;
106  }
107 
115  public function getDefaultConfigurationDescriptionFileLocation()
116  {
117  return $this->defaultConfigurationDescriptionFile;
118  }
119 
125  public function getLocalConfiguration()
126  {
127  return require $this->getLocalConfigurationFileLocation();
128  }
129 
137  public function getLocalConfigurationFileLocation()
138  {
139  return ‪Environment::getLegacyConfigPath() . '/' . $this->localConfigurationFile;
140  }
141 
147  public function getMergedLocalConfiguration(): array
148  {
149  $localConfiguration = $this->getDefaultConfiguration();
150  ‪ArrayUtility::mergeRecursiveWithOverrule($localConfiguration, $this->getLocalConfiguration());
151  return $localConfiguration;
152  }
153 
161  public function getAdditionalConfigurationFileLocation()
162  {
163  return ‪Environment::getLegacyConfigPath() . '/' . $this->additionalConfigurationFile;
164  }
165 
171  protected function getFactoryConfigurationFileLocation()
172  {
173  return $this->factoryConfigurationFile;
174  }
175 
181  protected function getAdditionalFactoryConfigurationFileLocation()
182  {
183  return ‪Environment::getLegacyConfigPath() . '/' . $this->additionalFactoryConfigurationFile;
184  }
185 
191  public function updateLocalConfiguration(array $configurationToMerge)
192  {
193  $newLocalConfiguration = $this->getLocalConfiguration();
194  ‪ArrayUtility::mergeRecursiveWithOverrule($newLocalConfiguration, $configurationToMerge);
195  $this->writeLocalConfiguration($newLocalConfiguration);
196  }
197 
204  public function getDefaultConfigurationValueByPath($path)
205  {
206  return ‪ArrayUtility::getValueByPath($this->getDefaultConfiguration(), $path);
207  }
208 
215  public function getLocalConfigurationValueByPath($path)
216  {
217  return ‪ArrayUtility::getValueByPath($this->getLocalConfiguration(), $path);
218  }
219 
227  public function getConfigurationValueByPath($path)
228  {
229  $defaultConfiguration = $this->getDefaultConfiguration();
230  ‪ArrayUtility::mergeRecursiveWithOverrule($defaultConfiguration, $this->getLocalConfiguration());
231  return ‪ArrayUtility::getValueByPath($defaultConfiguration, $path);
232  }
233 
244  public function setLocalConfigurationValueByPath($path, $value)
245  {
246  $result = false;
247  if ($this->isValidLocalConfigurationPath($path)) {
248  $localConfiguration = $this->getLocalConfiguration();
249  $localConfiguration = ‪ArrayUtility::setValueByPath($localConfiguration, $path, $value);
250  $result = $this->writeLocalConfiguration($localConfiguration);
251  }
252  return $result;
253  }
254 
261  public function setLocalConfigurationValuesByPathValuePairs(array $pairs)
262  {
263  $localConfiguration = $this->getLocalConfiguration();
264  foreach ($pairs as $path => $value) {
265  if ($this->isValidLocalConfigurationPath($path)) {
266  $localConfiguration = ‪ArrayUtility::setValueByPath($localConfiguration, $path, $value);
267  }
268  }
269  return $this->writeLocalConfiguration($localConfiguration);
270  }
271 
278  public function removeLocalConfigurationKeysByPath(array $keys)
279  {
280  $result = false;
281  $localConfiguration = $this->getLocalConfiguration();
282  foreach ($keys as $path) {
283  // Remove key if path is within LocalConfiguration
284  if (‪ArrayUtility::isValidPath($localConfiguration, $path)) {
285  $result = true;
286  $localConfiguration = ‪ArrayUtility::removeByPath($localConfiguration, $path);
287  }
288  }
289  if ($result) {
290  $this->writeLocalConfiguration($localConfiguration);
291  }
292  return $result;
293  }
294 
305  public function enableFeature(string $featureName): bool
306  {
307  return $this->setLocalConfigurationValueByPath('SYS/features/' . $featureName, true);
308  }
309 
320  public function disableFeature(string $featureName): bool
321  {
322  return $this->setLocalConfigurationValueByPath('SYS/features/' . $featureName, false);
323  }
324 
331  public function canWriteConfiguration()
332  {
333  $fileLocation = $this->getLocalConfigurationFileLocation();
334  return @is_writable(file_exists($fileLocation) ? $fileLocation : ‪Environment::getLegacyConfigPath() . '/');
335  }
336 
343  public function exportConfiguration()
344  {
345  if (@is_file($this->getLocalConfigurationFileLocation())) {
346  $localConfiguration = $this->getLocalConfiguration();
347  if (is_array($localConfiguration)) {
348  $defaultConfiguration = $this->getDefaultConfiguration();
349  ‪ArrayUtility::mergeRecursiveWithOverrule($defaultConfiguration, $localConfiguration);
350  ‪$GLOBALS['TYPO3_CONF_VARS'] = $defaultConfiguration;
351  } else {
352  throw new \UnexpectedValueException('LocalConfiguration invalid.', 1349272276);
353  }
354  } else {
355  // No LocalConfiguration (yet), load DefaultConfiguration
356  ‪$GLOBALS['TYPO3_CONF_VARS'] = $this->getDefaultConfiguration();
357  }
358 
359  // Load AdditionalConfiguration
360  if (@is_file($this->getAdditionalConfigurationFileLocation())) {
361  require $this->getAdditionalConfigurationFileLocation();
362  }
363  }
364 
373  public function writeLocalConfiguration(array $configuration)
374  {
375  $localConfigurationFile = $this->getLocalConfigurationFileLocation();
376  if (!$this->canWriteConfiguration()) {
377  throw new \RuntimeException(
378  $localConfigurationFile . ' is not writable.',
379  1346323822
380  );
381  }
382  $configuration = ‪ArrayUtility::sortByKeyRecursive($configuration);
384  $localConfigurationFile,
385  "<?php\n" .
386  'return ' .
387  ‪ArrayUtility::arrayExport($configuration) .
388  ";\n",
389  true
390  );
391 
392  GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive($localConfigurationFile);
393 
394  return $result;
395  }
396 
405  public function writeAdditionalConfiguration(array $additionalConfigurationLines)
406  {
408  $this->getAdditionalConfigurationFileLocation(),
409  "<?php\n" . implode("\n", $additionalConfigurationLines) . "\n"
410  );
411  }
412 
421  public function createLocalConfigurationFromFactoryConfiguration()
422  {
423  if (file_exists($this->getLocalConfigurationFileLocation())) {
424  throw new \RuntimeException(
425  'LocalConfiguration.php exists already',
426  1364836026
427  );
428  }
429  $localConfigurationArray = require $this->getFactoryConfigurationFileLocation();
430  $additionalFactoryConfigurationFileLocation = $this->getAdditionalFactoryConfigurationFileLocation();
431  if (file_exists($additionalFactoryConfigurationFileLocation)) {
432  $additionalFactoryConfigurationArray = require $additionalFactoryConfigurationFileLocation;
434  $localConfigurationArray,
435  $additionalFactoryConfigurationArray
436  );
437  }
438  $randomKey = GeneralUtility::makeInstance(Random::class)->generateRandomHexString(96);
439  $localConfigurationArray['SYS']['encryptionKey'] = $randomKey;
440 
441  $this->writeLocalConfiguration($localConfigurationArray);
442  }
443 
450  protected function isValidLocalConfigurationPath($path)
451  {
452  // Early return for white listed paths
453  foreach ($this->whiteListedLocalConfigurationPaths as $whiteListedPath) {
454  if (str_starts_with($path, $whiteListedPath)) {
455  return true;
456  }
457  }
458  return ‪ArrayUtility::isValidPath($this->getDefaultConfiguration(), $path);
459  }
460 }
‪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\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:25
‪TYPO3\CMS\Core\Configuration
Definition: ConfigurationManager.php:16
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:43
‪TYPO3\CMS\Core\Crypto\Random
Definition: Random.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1722
‪TYPO3\CMS\Core\Core\Environment\getLegacyConfigPath
‪static string getLegacyConfigPath()
Definition: Environment.php:308