[TASK] Move DefaultConfigurationDescription to Yaml format
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Service / LocalConfigurationValueService.php
1 <?php
2 declare(strict_types=1);
3 namespace TYPO3\CMS\Install\Service;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
19 use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader;
20 use TYPO3\CMS\Core\Messaging\FlashMessage;
21 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23
24 /**
25 * Service handling bulk read and write of LocalConfiguration values.
26 *
27 * Used by "Configure global settings" / "All configuration" view.
28 */
29 class LocalConfigurationValueService
30 {
31
32 /**
33 * Get up configuration data. Prepares main TYPO3_CONF_VARS
34 * array to be displayed and merges is with the description file
35 *
36 * @return array Configuration data
37 */
38 public function getCurrentConfigurationData(): array
39 {
40 $data = [];
41 $typo3ConfVars = array_keys($GLOBALS['TYPO3_CONF_VARS']);
42 sort($typo3ConfVars);
43 $commentArray = $this->getDefaultConfigArrayComments();
44 foreach ($typo3ConfVars as $sectionName) {
45 $data[$sectionName] = [];
46
47 foreach ($GLOBALS['TYPO3_CONF_VARS'][$sectionName] as $key => $value) {
48 $descriptionInfo = $commentArray[$sectionName]['items'][$key];
49 $descriptionType = $descriptionInfo['type'];
50 if (!is_array($value) && (!preg_match('/[' . LF . CR . ']/', (string)$value) || $descriptionType === 'multiline')) {
51 $itemData = [];
52 $itemData['key'] = $key;
53 $itemData['fieldType'] = $descriptionInfo['type'];
54 $itemData['description'] = $descriptionInfo['description'];
55 $itemData['allowedValues'] = $descriptionInfo['allowedValues'];
56 $itemData['key'] = $key;
57 switch ($descriptionType) {
58 case 'multiline':
59 $itemData['type'] = 'textarea';
60 $itemData['value'] = str_replace(['\' . LF . \'', '\' . LF . \''], [LF, LF], $value);
61 break;
62 case 'bool':
63 $itemData['type'] = 'checkbox';
64 $itemData['value'] = $value ? '1' : '0';
65 $itemData['checked'] = (bool)$value;
66 break;
67 case 'int':
68 $itemData['type'] = 'number';
69 $itemData['value'] = (int)$value;
70 break;
71 // Check if the setting is a PHP error code, will trigger a view helper in fluid
72 case 'errors':
73 $itemData['type'] = 'input';
74 $itemData['value'] = $value;
75 $itemData['phpErrorCode'] = true;
76 break;
77 default:
78 $itemData['type'] = 'input';
79 $itemData['value'] = $value;
80 }
81
82 $data[$sectionName][] = $itemData;
83 }
84 }
85 }
86 return $data;
87 }
88
89 /**
90 * Store changed values in LocalConfiguration
91 *
92 * @param array $valueList Nested array with key['key'] value
93 * @return FlashMessageQueue
94 */
95 public function updateLocalConfigurationValues(array $valueList): FlashMessageQueue
96 {
97 $messageQueue = new FlashMessageQueue('install');
98 $configurationPathValuePairs = [];
99 $commentArray = $this->getDefaultConfigArrayComments();
100 $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
101 foreach ($valueList as $path => $value) {
102 $oldValue = $configurationManager->getConfigurationValueByPath($path);
103 $pathParts = explode('/', $path);
104 $descriptionData = $commentArray[$pathParts[0]]['items'][$pathParts[1]];
105 $dataType = $descriptionData['type'];
106
107 if ($dataType === 'multiline') {
108 // Force Unix line breaks in text areas
109 $value = str_replace(CR, '', $value);
110 // Preserve line breaks
111 $value = str_replace(LF, '\' . LF . \'', $value);
112 }
113
114 if ($dataType === 'bool') {
115 // When submitting settings in the Install Tool, values that default to "FALSE" or "TRUE"
116 // in EXT:core/Configuration/DefaultConfiguration.php will be sent as "0" resp. "1".
117 $value = $value === '1';
118 $valueHasChanged = (bool)$oldValue !== $value;
119 } elseif ($dataType === 'int') {
120 // Cast integer values to integers (but only for values that can not contain a string as well)
121 $value = (int)$value;
122 $valueHasChanged = (int)$oldValue !== $value;
123 } else {
124 $valueHasChanged = (string)$oldValue !== (string)$value;
125 }
126
127 // Save if value changed
128 if ($valueHasChanged) {
129 $configurationPathValuePairs[$path] = $value;
130 if (is_bool($value)) {
131 $messageBody = 'New value = ' . ($value ? 'true' : 'false');
132 } else {
133 $messageBody = 'New value = ' . $value;
134 }
135 $messageQueue->enqueue(new FlashMessage(
136 $messageBody,
137 $path
138 ));
139 }
140 }
141 if (!empty($messageQueue)) {
142 $configurationManager->setLocalConfigurationValuesByPathValuePairs($configurationPathValuePairs);
143 }
144 return $messageQueue;
145 }
146
147 /**
148 * Returns an array of available sections and their description
149 *
150 * @return string[]
151 */
152 public function getSpeakingSectionNames(): array
153 {
154 return [
155 'BE' => 'Backend',
156 'DB' => 'Database',
157 'EXT' => 'Extension Installation',
158 'FE' => 'Frontend',
159 'GFX' => 'Image Processing',
160 'HTTP' => 'Connection',
161 'MAIL' => 'Mail',
162 'SYS' => 'System'
163 ];
164 }
165
166 /**
167 * Read descriptions from description file
168 *
169 * @return array
170 */
171 protected function getDefaultConfigArrayComments(): array
172 {
173 $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
174 $fileName = $configurationManager->getDefaultConfigurationDescriptionFileLocation();
175 $fileLoader = GeneralUtility::makeInstance(YamlFileLoader::class);
176 return $fileLoader->load($fileName);
177 }
178 }