[!!!][FEATURE] Main install tool refactoring
[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\Utility\ArrayUtility;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Install\Status\OkStatus;
22
23 /**
24 * Service handling bulk read and write of LocalConfiguration values.
25 *
26 * Used by "Configure global settings" / "All configuration" view.
27 */
28 class LocalConfigurationValueService
29 {
30 /**
31 * Error handlers are a bit mask in PHP. This register hints the View to
32 * add a fluid view helper resolving the bit mask to its representation
33 * as constants again for the specified items in ['SYS'].
34 *
35 * @var array
36 */
37 protected $phpErrorCodesSettings = [
38 'errorHandlerErrors',
39 'exceptionalErrors',
40 'syslogErrorReporting',
41 'belogErrorReporting',
42 ];
43
44 /**
45 * Get up configuration data. Prepares main TYPO3_CONF_VARS
46 * array to be displayed and merges is with the description file
47 *
48 * @return array Configuration data
49 */
50 public function getCurrentConfigurationData(): array
51 {
52 $data = [];
53 $typo3ConfVars = array_keys($GLOBALS['TYPO3_CONF_VARS']);
54 sort($typo3ConfVars);
55 $commentArray = $this->getDefaultConfigArrayComments();
56 foreach ($typo3ConfVars as $sectionName) {
57 $data[$sectionName] = [];
58
59 foreach ($GLOBALS['TYPO3_CONF_VARS'][$sectionName] as $key => $value) {
60 $description = trim((string)$commentArray[$sectionName][$key]);
61 $isTextarea = (bool)preg_match('/^(<.*?>)?string \\(textarea\\)/i', $description);
62 $doNotRender = (bool)preg_match('/^(<.*?>)?string \\(exclude\\)/i', $description);
63
64 if (!is_array($value) && !$doNotRender && (!preg_match('/[' . LF . CR . ']/', (string)$value) || $isTextarea)) {
65 $itemData = [];
66 $itemData['key'] = $key;
67 $itemData['description'] = $description;
68 if ($isTextarea) {
69 $itemData['type'] = 'textarea';
70 $itemData['value'] = str_replace(['\' . LF . \'', '\' . LF . \''], [LF, LF], $value);
71 } elseif (preg_match('/^(<.*?>)?boolean/i', $description)) {
72 $itemData['type'] = 'checkbox';
73 $itemData['value'] = $value ? '1' : '0';
74 $itemData['checked'] = (bool)$value;
75 } elseif (preg_match('/^(<.*?>)?integer/i', $description)) {
76 $itemData['type'] = 'number';
77 $itemData['value'] = (int)$value;
78 } else {
79 $itemData['type'] = 'input';
80 $itemData['value'] = $value;
81 }
82
83 // Check if the setting is a PHP error code, will trigger a view helper in fluid
84 if ($sectionName === 'SYS' && in_array($key, $this->phpErrorCodesSettings)) {
85 $itemData['phpErrorCode'] = true;
86 }
87
88 $data[$sectionName][] = $itemData;
89 }
90 }
91 }
92 return $data;
93 }
94
95 /**
96 * Store changed values in LocalConfiguration
97 *
98 * @param array $valueList Nested array with key['key'] value
99 * @return array StatusInterface[]
100 */
101 public function updateLocalConfigurationValues(array $valueList): array
102 {
103 $statusObjects = [];
104 $configurationPathValuePairs = [];
105 $commentArray = $this->getDefaultConfigArrayComments();
106 $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
107 foreach ($valueList as $path => $value) {
108 $oldValue = $configurationManager->getConfigurationValueByPath($path);
109 $description = ArrayUtility::getValueByPath($commentArray, $path);
110
111 if (preg_match('/^string \\(textarea\\)/i', $description)) {
112 // Force Unix line breaks in text areas
113 $value = str_replace(CR, '', $value);
114 // Preserve line breaks
115 $value = str_replace(LF, '\' . LF . \'', $value);
116 }
117
118 if (preg_match('/^(<.*?>)?boolean/i', $description)) {
119 // When submitting settings in the Install Tool, values that default to "FALSE" or "TRUE"
120 // in EXT:core/Configuration/DefaultConfiguration.php will be sent as "0" resp. "1".
121 $value = $value === '1';
122 $valueHasChanged = (bool)$oldValue !== $value;
123 } elseif (preg_match('/^(<.*?>)?integer/i', $description)) {
124 // Cast integer values to integers (but only for values that can not contain a string as well)
125 $value = (int)$value;
126 $valueHasChanged = (int)$oldValue !== $value;
127 } else {
128 $valueHasChanged = (string)$oldValue !== (string)$value;
129 }
130
131 // Save if value changed
132 if ($valueHasChanged) {
133 $configurationPathValuePairs[$path] = $value;
134 $status = GeneralUtility::makeInstance(OkStatus::class);
135 $status->setTitle($path);
136 if (is_bool($value)) {
137 $status->setMessage('New value = ' . ($value ? 'true' : 'false'));
138 } else {
139 $status->setMessage('New value = ' . $value);
140 }
141 $statusObjects[] = $status;
142 }
143 }
144 if (!empty($statusObjects)) {
145 $configurationManager->setLocalConfigurationValuesByPathValuePairs($configurationPathValuePairs);
146 }
147 return $statusObjects;
148 }
149
150 /**
151 * Returns an array of available sections and their description
152 *
153 * @return string[]
154 */
155 public function getSpeakingSectionNames(): array
156 {
157 return [
158 'BE' => 'Backend',
159 'DB' => 'Database',
160 'EXT' => 'Extension Installation',
161 'FE' => 'Frontend',
162 'GFX' => 'Image Processing',
163 'HTTP' => 'Connection',
164 'MAIL' => 'Mail',
165 'SYS' => 'System'
166 ];
167 }
168
169 /**
170 * Read descriptions from description file
171 *
172 * @return array
173 */
174 protected function getDefaultConfigArrayComments(): array
175 {
176 $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
177 return require $configurationManager->getDefaultConfigurationDescriptionFileLocation();
178 }
179 }