[TASK] Fix typos & grammar issues in Install Tool
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Service / SilentConfigurationUpgradeService.php
1 <?php
2 namespace TYPO3\CMS\Install\Service;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30 /**
31 * Execute "silent" LocalConfiguration upgrades if needed.
32 *
33 * Some LocalConfiguration settings are obsolete or changed over time.
34 * This class handles upgrades of these settings. It is called by
35 * the step controller at an early point.
36 *
37 * Every change is encapsulated in one method an must throw a RedirectException
38 * if new data is written to LocalConfiguration. This is caught by above
39 * step controller to initiate a redirect and start again with adapted configuration.
40 */
41 class SilentConfigurationUpgradeService {
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
45 * @inject
46 */
47 protected $objectManager = NULL;
48
49 /**
50 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
51 * @inject
52 */
53 protected $configurationManager = NULL;
54
55 /**
56 * @var array List of obsolete configuration options in LocalConfiguration to be removed
57 */
58 protected $obsoleteLocalConfigurationSettings = array(
59 // #34092
60 'BE/forceCharset',
61 // #26519
62 'BE/loginLabels',
63 // #44506
64 'BE/loginNews',
65 // #52013
66 'BE/TSconfigConditions',
67 // #30613
68 'BE/useOnContextMenuHandler',
69 // #48179
70 'EXT/em_mirrorListURL',
71 'EXT/em_wsdlURL',
72 // #43094
73 'EXT/extList',
74 // #35877
75 'EXT/extList_FE',
76 // #41813
77 'EXT/noEdit',
78 // #26090
79 'FE/defaultTypoScript_editorcfg',
80 'FE/defaultTypoScript_editorcfg.',
81 // #25099
82 'FE/simulateStaticDocuments',
83 // #52786
84 'FE/logfile_dir',
85 // #52011
86 'GFX/im_combine_filename',
87 // #52088
88 'GFX/im_imvMaskState',
89 // #22687
90 'GFX/gdlib_2',
91 // #52012
92 'GFX/im_mask_temp_ext_noloss',
93 // #52088
94 'GFX/im_negate_mask',
95 // #52010
96 'GFX/im_no_effects',
97 // #18431
98 'GFX/noIconProc',
99 // #17606
100 'GFX/TTFLocaleConv',
101 // #39164
102 'SYS/additionalAllowedClassPrefixes',
103 // #27689
104 'SYS/caching/cacheBackends',
105 'SYS/caching/cacheFrontends',
106 // #38414
107 'SYS/extCache',
108 // #35923
109 'SYS/multiplyDBfieldSize',
110 // #46993
111 'SYS/T3instID',
112 // #52857
113 'SYS/forceReturnPath',
114 );
115
116 /**
117 * Executed configuration upgrades. Single upgrade methods must throw a
118 * RedirectException if something was written to LocalConfiguration.
119 *
120 * @return void
121 */
122 public function execute() {
123 $this->generateEncryptionKeyIfNeeded();
124 $this->configureBackendLoginSecurity();
125 $this->configureSaltedPasswords();
126 $this->setProxyAuthScheme();
127 $this->disableImageMagickAndGdlibIfImageProcessingIsDisabled();
128 $this->disableImageMagickDetailSettingsIfImageMagickIsDisabled();
129 $this->setImageMagickDetailSettings();
130 $this->addFileTableToDefaultCategorizedTablesIfAlreadyCustomized();
131 $this->removeObsoleteLocalConfigurationSettings();
132 }
133
134 /**
135 * Some settings in LocalConfiguration vanished in DefaultConfiguration
136 * and have no impact on the core anymore.
137 * To keep the configuration clean, those old settings are just silently
138 * removed from LocalConfiguration if set.
139 *
140 * @return void
141 */
142 protected function removeObsoleteLocalConfigurationSettings() {
143 $removed = $this->configurationManager->removeLocalConfigurationKeysByPath($this->obsoleteLocalConfigurationSettings);
144
145 // The old default value is not needed anymore. So if the user
146 // did not set a different value we can remove it.
147 $currentSetDbInitValue = $this->configurationManager->getConfigurationValueByPath('SYS/setDBinit');
148 if (preg_match('/^\s*SET\s+NAMES\s+[\'"]?utf8[\'"]?\s*[;]?\s*$/i', $currentSetDbInitValue) === 1) {
149 $removed = $removed || $this->configurationManager->removeLocalConfigurationKeysByPath(array('SYS/setDBinit'));
150 }
151
152 // If something was changed: Trigger a reload to have new values in next request
153 if ($removed) {
154 $this->throwRedirectException();
155 }
156 }
157
158 /**
159 * Backend login security is set to rsa if rsaauth
160 * is installed (but not used) otherwise the default value "normal" has to be used.
161 * This forces either 'normal' or 'rsa' to be set in LocalConfiguration.
162 *
163 * @return void
164 */
165 protected function configureBackendLoginSecurity() {
166 try {
167 $currentLoginSecurityLevelValue = $this->configurationManager->getLocalConfigurationValueByPath('BE/loginSecurityLevel');
168 if (ExtensionManagementUtility::isLoaded('rsaauth')
169 && $currentLoginSecurityLevelValue !== 'rsa'
170 ) {
171 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
172 $this->throwRedirectException();
173 } elseif (!ExtensionManagementUtility::isLoaded('rsaauth')
174 && $currentLoginSecurityLevelValue !== 'normal'
175 ) {
176 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
177 $this->throwRedirectException();
178 }
179 } catch (\RuntimeException $e) {
180 // If an exception is thrown, the value is not set in LocalConfiguration
181 if (ExtensionManagementUtility::isLoaded('rsaauth')) {
182 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
183 $this->throwRedirectException();
184 } elseif (!ExtensionManagementUtility::isLoaded('rsaauth')) {
185 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
186 $this->throwRedirectException();
187 }
188 }
189 }
190
191 /**
192 * Check the settings for salted passwords extension to load it as a required extension.
193 * Unset obsolete configuration options if given.
194 *
195 * @return void
196 */
197 protected function configureSaltedPasswords() {
198 $defaultConfiguration = $this->configurationManager->getDefaultConfiguration();
199 $defaultExtensionConfiguration = unserialize($defaultConfiguration['EXT']['extConf']['saltedpasswords']);
200 try {
201 $extensionConfiguration = @unserialize($this->configurationManager->getLocalConfigurationValueByPath('EXT/extConf/saltedpasswords'));
202 } catch (\RuntimeException $e) {
203 $extensionConfiguration = array();
204 }
205 if (is_array($extensionConfiguration) && !empty($extensionConfiguration)) {
206 if (isset($extensionConfiguration['BE.']['enabled'])) {
207 if ($extensionConfiguration['BE.']['enabled']) {
208 unset($extensionConfiguration['BE.']['enabled']);
209 } else {
210 $extensionConfiguration['BE.'] = $defaultExtensionConfiguration['BE.'];
211 }
212 $this->configurationManager->setLocalConfigurationValueByPath(
213 'EXT/extConf/saltedpasswords',
214 serialize($extensionConfiguration)
215 );
216 $this->throwRedirectException();
217 }
218 } else {
219 $this->configurationManager->setLocalConfigurationValueByPath(
220 'EXT/extConf/saltedpasswords',
221 serialize($defaultExtensionConfiguration)
222 );
223 $this->throwRedirectException();
224 }
225 }
226
227 /**
228 * The encryption key is crucial for securing form tokens
229 * and the whole TYPO3 link rendering later on. A random key is set here in
230 * LocalConfiguration if it does not exist yet. This might possible happen
231 * during upgrading and will happen during first install.
232 *
233 * @return void
234 */
235 protected function generateEncryptionKeyIfNeeded() {
236 try{
237 $currentValue = $this->configurationManager->getLocalConfigurationValueByPath('SYS/encryptionKey');
238 } catch (\RuntimeException $e) {
239 // If an exception is thrown, the value is not set in LocalConfiguration
240 $currentValue = '';
241 }
242
243 if (empty($currentValue)) {
244 $randomKey = GeneralUtility::getRandomHexString(96);
245 $this->configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $randomKey);
246 $this->throwRedirectException();
247 }
248 }
249
250 /**
251 * $GLOBALS['TYPO3_CONF_VARS']['HTTP']['proxy_auth_scheme'] must be either
252 * 'digest' or 'basic'. 'basic' is default in DefaultConfiguration, so the
253 * setting can be removed from LocalConfiguration if it is not set to 'digest'.
254 *
255 * @return void
256 */
257 protected function setProxyAuthScheme() {
258 // Get current value from LocalConfiguration
259 try {
260 $currentValueInLocalConfiguration = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_auth_scheme');
261 } catch (\RuntimeException $e) {
262 // If an exception is thrown, the value is not set in LocalConfiguration, so we don't need to do anything
263 return;
264 }
265 if ($currentValueInLocalConfiguration !== 'digest') {
266 $this->configurationManager->removeLocalConfigurationKeysByPath(array('HTTP/proxy_auth_scheme'));
267 $this->throwRedirectException();
268 }
269 }
270
271 /**
272 * GFX/im and GFX/gdlib must be set to 0 if image_processing is disabled.
273 *
274 * "Configuration presets" in install tool is not type safe, so value
275 * comparisons here are not type safe too, to not trigger changes to
276 * LocalConfiguration again.
277 *
278 * @return void
279 */
280 protected function disableImageMagickAndGdlibIfImageProcessingIsDisabled() {
281 $changedValues = array();
282 try {
283 $currentImageProcessingValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/image_processing');
284 } catch (\RuntimeException $e) {
285 $currentImageProcessingValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/image_processing');
286 }
287 try {
288 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im');
289 } catch (\RuntimeException $e) {
290 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im');
291 }
292 try {
293 $currentGdlibValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/gdlib');
294 } catch (\RuntimeException $e) {
295 $currentGdlibValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/gdlib');
296 }
297 // If image processing is fully disabled, im and gdlib sub settings must be 0
298 if (!$currentImageProcessingValue) {
299 if ($currentImValue != 0) {
300 $changedValues['GFX/im'] = 0;
301 }
302 if ($currentGdlibValue != 0) {
303 $changedValues['GFX/gdlib'] = 0;
304 }
305 }
306 if (count($changedValues) > 0) {
307 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
308 $this->throwRedirectException();
309 }
310 }
311
312 /**
313 * Detail configuration of Image Magick settings must be cleared
314 * if Image Magick handling is disabled.
315 *
316 * "Configuration presets" in install tool is not type safe, so value
317 * comparisons here are not type safe too, to not trigger changes to
318 * LocalConfiguration again.
319 *
320 * @return void
321 */
322 protected function disableImageMagickDetailSettingsIfImageMagickIsDisabled() {
323 $changedValues = array();
324 try {
325 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im');
326 }
327 catch (\RuntimeException $e) {
328 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im');
329 }
330 try {
331 $currentImPathValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_path');
332 }
333 catch (\RuntimeException $e) {
334 $currentImPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_path');
335 }
336 try {
337 $currentImPathLzwValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_path_lzw');
338 }
339 catch (\RuntimeException $e) {
340 $currentImPathLzwValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_path_lzw');
341 }
342 try {
343 $currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext');
344 }
345 catch (\RuntimeException $e) {
346 $currentImageFileExtValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/imagefile_ext');
347 }
348 try {
349 $currentThumbnailsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails');
350 }
351 catch (\RuntimeException $e) {
352 $currentThumbnailsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails');
353 }
354 if (!$currentImValue) {
355 if ($currentImPathValue != '') {
356 $changedValues['GFX/im_path'] = '';
357 }
358 if ($currentImPathLzwValue != '') {
359 $changedValues['GFX/im_path_lzw'] = '';
360 }
361 if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') {
362 $changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png';
363 }
364 if ($currentThumbnailsValue != 0) {
365 $changedValues['GFX/thumbnails'] = 0;
366 }
367 }
368 if (count($changedValues) > 0) {
369 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
370 $this->throwRedirectException();
371 }
372 }
373
374 /**
375 * Detail configuration of Image Magick and Graphics Magick settings
376 * depending on main values.
377 *
378 * "Configuration presets" in install tool is not type safe, so value
379 * comparisons here are not type safe too, to not trigger changes to
380 * LocalConfiguration again.
381 *
382 * @return void
383 */
384 protected function setImageMagickDetailSettings() {
385 $changedValues = array();
386 try {
387 $currentIm5Value = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_version_5');
388 }
389 catch (\RuntimeException $e) {
390 $currentIm5Value = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_version_5');
391 }
392 try {
393 $currentImMaskValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
394 }
395 catch (\RuntimeException $e) {
396 $currentImMaskValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
397 }
398 try {
399 $currentIm5EffectsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_v5effects');
400 }
401 catch (\RuntimeException $e) {
402 $currentIm5EffectsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/im_v5effects');
403 }
404 if (strlen($currentIm5Value) > 0) {
405 if ($currentImMaskValue != 1) {
406 $changedValues['GFX/im_mask_temp_ext_gif'] = 1;
407 }
408 if ($currentIm5Value === 'gm') {
409 if ($currentIm5EffectsValue != -1) {
410 $changedValues['GFX/im_v5effects'] = -1;
411 }
412 }
413 }
414 if (count($changedValues) > 0) {
415 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
416 $this->throwRedirectException();
417 }
418 }
419
420 /**
421 * Make sure file table is categorized as of TYPO3 6.2. To enable DAM Migration
422 * sys_file_metadata table is included in DefaultConfiguration.
423 * If the setting already has been modified but does not contain sys_file_metadata: add it
424 *
425 * @return void
426 */
427 protected function addFileTableToDefaultCategorizedTablesIfAlreadyCustomized() {
428 /** @var \TYPO3\CMS\Core\Configuration\ConfigurationManager $configurationManager */
429 $configurationManager = $this->objectManager->get('TYPO3\\CMS\\Core\\Configuration\\ConfigurationManager');
430
431 $default = $configurationManager->getDefaultConfigurationValueByPath('SYS/defaultCategorizedTables');
432 try {
433 $actual = $configurationManager->getLocalConfigurationValueByPath('SYS/defaultCategorizedTables');
434 } catch(\RuntimeException $e) {
435 $actual = '';
436 }
437
438 $tables = GeneralUtility::trimExplode(',', $actual);
439 if ($actual !== '' && $actual !== $default && !in_array('sys_file_metadata', $tables)) {
440 $tables[] = 'sys_file_metadata';
441 $configurationManager->setLocalConfigurationValueByPath('SYS/defaultCategorizedTables', implode(',', $tables));
442 $this->throwRedirectException();
443 }
444 }
445
446 /**
447 * Throw exception after configuration change to trigger a redirect.
448 *
449 * @throws \TYPO3\CMS\Install\Controller\Exception\RedirectException
450 */
451 protected function throwRedirectException() {
452 throw new \TYPO3\CMS\Install\Controller\Exception\RedirectException(
453 'Configuration updated, reload needed',
454 1379024938
455 );
456 }
457 }