[!!!][TASK] Remove the explicitConfirmationOfTranslation setting
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / Service / SilentConfigurationUpgradeService.php
1 <?php
2 namespace TYPO3\CMS\Install\Service;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
18 use TYPO3\CMS\Core\Crypto\Random;
19 use TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Install\Service\Exception\ConfigurationChangedException;
23
24 /**
25 * Execute "silent" LocalConfiguration upgrades if needed.
26 *
27 * Some LocalConfiguration settings are obsolete or changed over time.
28 * This class handles upgrades of these settings. It is called by
29 * the step controller at an early point.
30 *
31 * Every change is encapsulated in one method an must throw a ConfigurationChangedException
32 * if new data is written to LocalConfiguration. This is caught by above
33 * step controller to initiate a redirect and start again with adapted configuration.
34 */
35 class SilentConfigurationUpgradeService
36 {
37 /**
38 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager
39 */
40 protected $configurationManager;
41
42 /**
43 * List of obsolete configuration options in LocalConfiguration to be removed
44 * Example:
45 * // #forge-ticket
46 * 'BE/somesetting',
47 *
48 * @var array
49 */
50 protected $obsoleteLocalConfigurationSettings = [
51 // #72400
52 'BE/spriteIconGenerator_handler',
53 // #72417
54 'SYS/lockingMode',
55 // #72473
56 'FE/secureFormmail',
57 'FE/strictFormmail',
58 'FE/formmailMaxAttachmentSize',
59 // #72337
60 'SYS/t3lib_cs_utils',
61 'SYS/t3lib_cs_convMethod',
62 // #72604
63 'SYS/maxFileNameLength',
64 // #72602
65 'BE/unzip_path',
66 // #72615
67 'BE/notificationPrefix',
68 // #72616
69 'BE/XCLASS',
70 'FE/XCLASS',
71 // #43085
72 'GFX/image_processing',
73 // #70056
74 'SYS/curlUse',
75 'SYS/curlProxyNTLM',
76 'SYS/curlProxyServer',
77 'SYS/curlProxyTunnel',
78 'SYS/curlProxyUserPass',
79 'SYS/curlTimeout',
80 // #75355
81 'BE/niceFlexFormXMLtags',
82 'BE/compactFlexFormXML',
83 // #75625
84 'SYS/clearCacheSystem',
85 // #77411
86 'SYS/caching/cacheConfigurations/extbase_typo3dbbackend_tablecolumns',
87 // #77460
88 'SYS/caching/cacheConfigurations/extbase_typo3dbbackend_queries',
89 // #79513
90 'FE/lockHashKeyWords',
91 'BE/lockHashKeyWords',
92 // #78835
93 'SYS/cookieHttpOnly',
94 // #71095
95 'BE/lang',
96 // #80050
97 'FE/cHashIncludePageId',
98 // #80711
99 'FE/noPHPscriptInclude',
100 'FE/maxSessionDataSize',
101 // #82162
102 'SYS/enable_errorDLOG',
103 'SYS/enable_exceptionDLOG',
104 // #82377
105 'EXT/allowSystemInstall',
106 // #82421
107 'SYS/sqlDebug',
108 'SYS/no_pconnect',
109 'SYS/setDBinit',
110 'SYS/dbClientCompress',
111 // #82430
112 'SYS/syslogErrorReporting',
113 // #82639
114 'SYS/enable_DLOG',
115 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLog',
116 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLogBE',
117 'SC_OPTIONS/t3lib/class.t3lib_userauth.php/writeDevLogFE',
118 // #82438
119 'SYS/enableDeprecationLog',
120 // #82680
121 'GFX/png_truecolor',
122 // #82803
123 'FE/content_doktypes',
124 // #83081
125 'BE/fileExtensions',
126 // #83768
127 'SYS/doNotCheckReferer',
128 // #83878
129 'SYS/isInitialInstallationInProgress',
130 'SYS/isInitialDatabaseImportDone',
131 // #84810
132 'BE/explicitConfirmationOfTranslation',
133 ];
134
135 public function __construct(ConfigurationManager $configurationManager = null)
136 {
137 $this->configurationManager = $configurationManager ?: GeneralUtility::makeInstance(ConfigurationManager::class);
138 }
139
140 /**
141 * Executed configuration upgrades. Single upgrade methods must throw a
142 * ConfigurationChangedException if something was written to LocalConfiguration.
143 */
144 public function execute()
145 {
146 $this->generateEncryptionKeyIfNeeded();
147 $this->configureBackendLoginSecurity();
148 $this->migrateImageProcessorSetting();
149 $this->transferHttpSettings();
150 $this->disableImageMagickDetailSettingsIfImageMagickIsDisabled();
151 $this->setImageMagickDetailSettings();
152 $this->migrateThumbnailsPngSetting();
153 $this->migrateLockSslSetting();
154 $this->migrateDatabaseConnectionSettings();
155 $this->migrateDatabaseConnectionCharset();
156 $this->migrateDatabaseDriverOptions();
157 $this->migrateLangDebug();
158 $this->migrateCacheHashOptions();
159 $this->migrateExceptionErrors();
160 $this->migrateDisplayErrorsSetting();
161
162 // Should run at the end to prevent that obsolete settings are removed before migration
163 $this->removeObsoleteLocalConfigurationSettings();
164 }
165
166 /**
167 * Some settings in LocalConfiguration vanished in DefaultConfiguration
168 * and have no impact on the core anymore.
169 * To keep the configuration clean, those old settings are just silently
170 * removed from LocalConfiguration if set.
171 */
172 protected function removeObsoleteLocalConfigurationSettings()
173 {
174 $removed = $this->configurationManager->removeLocalConfigurationKeysByPath($this->obsoleteLocalConfigurationSettings);
175
176 // If something was changed: Trigger a reload to have new values in next request
177 if ($removed) {
178 $this->throwConfigurationChangedException();
179 }
180 }
181
182 /**
183 * Backend login security is set to rsa if rsaauth
184 * is installed (but not used) otherwise the default value "normal" has to be used.
185 * This forces either 'normal' or 'rsa' to be set in LocalConfiguration.
186 */
187 protected function configureBackendLoginSecurity()
188 {
189 $rsaauthLoaded = ExtensionManagementUtility::isLoaded('rsaauth');
190 try {
191 $currentLoginSecurityLevelValue = $this->configurationManager->getLocalConfigurationValueByPath('BE/loginSecurityLevel');
192 if ($rsaauthLoaded && $currentLoginSecurityLevelValue !== 'rsa') {
193 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'rsa');
194 $this->throwConfigurationChangedException();
195 } elseif (!$rsaauthLoaded && $currentLoginSecurityLevelValue !== 'normal') {
196 $this->configurationManager->setLocalConfigurationValueByPath('BE/loginSecurityLevel', 'normal');
197 $this->throwConfigurationChangedException();
198 }
199 } catch (MissingArrayPathException $e) {
200 // If an exception is thrown, the value is not set in LocalConfiguration
201 $this->configurationManager->setLocalConfigurationValueByPath(
202 'BE/loginSecurityLevel',
203 $rsaauthLoaded ? 'rsa' : 'normal'
204 );
205 $this->throwConfigurationChangedException();
206 }
207 }
208
209 /**
210 * The encryption key is crucial for securing form tokens
211 * and the whole TYPO3 link rendering later on. A random key is set here in
212 * LocalConfiguration if it does not exist yet. This might possible happen
213 * during upgrading and will happen during first install.
214 */
215 protected function generateEncryptionKeyIfNeeded()
216 {
217 try {
218 $currentValue = $this->configurationManager->getLocalConfigurationValueByPath('SYS/encryptionKey');
219 } catch (MissingArrayPathException $e) {
220 // If an exception is thrown, the value is not set in LocalConfiguration
221 $currentValue = '';
222 }
223
224 if (empty($currentValue)) {
225 $randomKey = GeneralUtility::makeInstance(Random::class)->generateRandomHexString(96);
226 $this->configurationManager->setLocalConfigurationValueByPath('SYS/encryptionKey', $randomKey);
227 $this->throwConfigurationChangedException();
228 }
229 }
230
231 /**
232 * Parse old curl and HTTP options and set new HTTP options, related to Guzzle
233 */
234 protected function transferHttpSettings()
235 {
236 $changed = false;
237 $newParameters = [];
238 $obsoleteParameters = [];
239
240 // Remove / migrate options to new options
241 try {
242 // Check if the adapter option is set, if so, set it to the parameters that are obsolete
243 $this->configurationManager->getLocalConfigurationValueByPath('HTTP/adapter');
244 $obsoleteParameters[] = 'HTTP/adapter';
245 } catch (MissingArrayPathException $e) {
246 // Migration done already
247 }
248 try {
249 $newParameters['HTTP/version'] = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/protocol_version');
250 $obsoleteParameters[] = 'HTTP/protocol_version';
251 } catch (MissingArrayPathException $e) {
252 // Migration done already
253 }
254 try {
255 $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_verify_host');
256 $obsoleteParameters[] = 'HTTP/ssl_verify_host';
257 } catch (MissingArrayPathException $e) {
258 // Migration done already
259 }
260 try {
261 $legacyUserAgent = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/userAgent');
262 $newParameters['HTTP/headers/User-Agent'] = $legacyUserAgent;
263 $obsoleteParameters[] = 'HTTP/userAgent';
264 } catch (MissingArrayPathException $e) {
265 // Migration done already
266 }
267
268 // Redirects
269 try {
270 $legacyFollowRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/follow_redirects');
271 $obsoleteParameters[] = 'HTTP/follow_redirects';
272 } catch (MissingArrayPathException $e) {
273 $legacyFollowRedirects = '';
274 }
275 try {
276 $legacyMaximumRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/max_redirects');
277 $obsoleteParameters[] = 'HTTP/max_redirects';
278 } catch (MissingArrayPathException $e) {
279 $legacyMaximumRedirects = '';
280 }
281 try {
282 $legacyStrictRedirects = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/strict_redirects');
283 $obsoleteParameters[] = 'HTTP/strict_redirects';
284 } catch (MissingArrayPathException $e) {
285 $legacyStrictRedirects = '';
286 }
287
288 // Check if redirects have been disabled
289 if ($legacyFollowRedirects !== '' && (bool)$legacyFollowRedirects === false) {
290 $newParameters['HTTP/allow_redirects'] = false;
291 } elseif ($legacyMaximumRedirects !== '' || $legacyStrictRedirects !== '') {
292 $newParameters['HTTP/allow_redirects'] = [];
293 if ($legacyMaximumRedirects !== '' && (int)$legacyMaximumRedirects !== 5) {
294 $newParameters['HTTP/allow_redirects']['max'] = (int)$legacyMaximumRedirects;
295 }
296 if ($legacyStrictRedirects !== '' && (bool)$legacyStrictRedirects === true) {
297 $newParameters['HTTP/allow_redirects']['strict'] = true;
298 }
299 // defaults are used, no need to set the option in LocalConfiguration.php
300 if (empty($newParameters['HTTP/allow_redirects'])) {
301 unset($newParameters['HTTP/allow_redirects']);
302 }
303 }
304
305 // Migrate Proxy settings
306 try {
307 // Currently without protocol or port
308 $legacyProxyHost = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_host');
309 $obsoleteParameters[] = 'HTTP/proxy_host';
310 } catch (MissingArrayPathException $e) {
311 $legacyProxyHost = '';
312 }
313 try {
314 $legacyProxyPort = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_port');
315 $obsoleteParameters[] = 'HTTP/proxy_port';
316 } catch (MissingArrayPathException $e) {
317 $legacyProxyPort = '';
318 }
319 try {
320 $legacyProxyUser = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_user');
321 $obsoleteParameters[] = 'HTTP/proxy_user';
322 } catch (MissingArrayPathException $e) {
323 $legacyProxyUser = '';
324 }
325 try {
326 $legacyProxyPassword = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_password');
327 $obsoleteParameters[] = 'HTTP/proxy_password';
328 } catch (MissingArrayPathException $e) {
329 $legacyProxyPassword = '';
330 }
331 // Auth Scheme: Basic, digest etc.
332 try {
333 $legacyProxyAuthScheme = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/proxy_auth_scheme');
334 $obsoleteParameters[] = 'HTTP/proxy_auth_scheme';
335 } catch (MissingArrayPathException $e) {
336 $legacyProxyAuthScheme = '';
337 }
338
339 if ($legacyProxyHost !== '') {
340 $proxy = 'http://';
341 if ($legacyProxyAuthScheme !== '' && $legacyProxyUser !== '' && $legacyProxyPassword !== '') {
342 $proxy .= $legacyProxyUser . ':' . $legacyProxyPassword . '@';
343 }
344 $proxy .= $legacyProxyHost;
345 if ($legacyProxyPort !== '') {
346 $proxy .= ':' . $legacyProxyPort;
347 }
348 $newParameters['HTTP/proxy'] = $proxy;
349 }
350
351 // Verify peers
352 // see http://docs.guzzlephp.org/en/latest/request-options.html#verify
353 try {
354 $legacySslVerifyPeer = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_verify_peer');
355 $obsoleteParameters[] = 'HTTP/ssl_verify_peer';
356 } catch (MissingArrayPathException $e) {
357 $legacySslVerifyPeer = '';
358 }
359
360 // Directory holding multiple Certificate Authority files
361 try {
362 $legacySslCaPath = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_capath');
363 $obsoleteParameters[] = 'HTTP/ssl_capath';
364 } catch (MissingArrayPathException $e) {
365 $legacySslCaPath = '';
366 }
367 // Certificate Authority file to verify the peer with (use when ssl_verify_peer is TRUE)
368 try {
369 $legacySslCaFile = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_cafile');
370 $obsoleteParameters[] = 'HTTP/ssl_cafile';
371 } catch (MissingArrayPathException $e) {
372 $legacySslCaFile = '';
373 }
374 if ($legacySslVerifyPeer !== '') {
375 if ($legacySslCaFile !== '' && $legacySslCaPath !== '') {
376 $newParameters['HTTP/verify'] = $legacySslCaPath . $legacySslCaFile;
377 } elseif ((bool)$legacySslVerifyPeer === false) {
378 $newParameters['HTTP/verify'] = false;
379 }
380 }
381
382 // SSL Key + Passphrase
383 // Name of a file containing local certificate
384 try {
385 $legacySslLocalCert = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_local_cert');
386 $obsoleteParameters[] = 'HTTP/ssl_local_cert';
387 } catch (MissingArrayPathException $e) {
388 $legacySslLocalCert = '';
389 }
390
391 // Passphrase with which local certificate was encoded
392 try {
393 $legacySslPassphrase = $this->configurationManager->getLocalConfigurationValueByPath('HTTP/ssl_passphrase');
394 $obsoleteParameters[] = 'HTTP/ssl_passphrase';
395 } catch (MissingArrayPathException $e) {
396 $legacySslPassphrase = '';
397 }
398
399 if ($legacySslLocalCert !== '') {
400 if ($legacySslPassphrase !== '') {
401 $newParameters['HTTP/ssl_key'] = [
402 $legacySslLocalCert,
403 $legacySslPassphrase
404 ];
405 } else {
406 $newParameters['HTTP/ssl_key'] = $legacySslLocalCert;
407 }
408 }
409
410 // Update the LocalConfiguration file if obsolete parameters or new parameters are set
411 if (!empty($obsoleteParameters)) {
412 $this->configurationManager->removeLocalConfigurationKeysByPath($obsoleteParameters);
413 $changed = true;
414 }
415 if (!empty($newParameters)) {
416 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($newParameters);
417 $changed = true;
418 }
419 if ($changed) {
420 $this->throwConfigurationChangedException();
421 }
422 }
423
424 /**
425 * Detail configuration of Image Magick settings must be cleared
426 * if Image Magick handling is disabled.
427 *
428 * "Configuration presets" in install tool is not type safe, so value
429 * comparisons here are not type safe too, to not trigger changes to
430 * LocalConfiguration again.
431 */
432 protected function disableImageMagickDetailSettingsIfImageMagickIsDisabled()
433 {
434 $changedValues = [];
435 try {
436 $currentImValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_enabled');
437 } catch (MissingArrayPathException $e) {
438 $currentImValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_enabled');
439 }
440
441 try {
442 $currentImPathValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_path');
443 } catch (MissingArrayPathException $e) {
444 $currentImPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path');
445 }
446
447 try {
448 $currentImPathLzwValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_path_lzw');
449 } catch (MissingArrayPathException $e) {
450 $currentImPathLzwValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path_lzw');
451 }
452
453 try {
454 $currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext');
455 } catch (MissingArrayPathException $e) {
456 $currentImageFileExtValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/imagefile_ext');
457 }
458
459 try {
460 $currentThumbnailsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails');
461 } catch (MissingArrayPathException $e) {
462 $currentThumbnailsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails');
463 }
464
465 if (!$currentImValue) {
466 if ($currentImPathValue != '') {
467 $changedValues['GFX/processor_path'] = '';
468 }
469 if ($currentImPathLzwValue != '') {
470 $changedValues['GFX/processor_path_lzw'] = '';
471 }
472 if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') {
473 $changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png';
474 }
475 if ($currentThumbnailsValue != 0) {
476 $changedValues['GFX/thumbnails'] = 0;
477 }
478 }
479 if (!empty($changedValues)) {
480 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
481 $this->throwConfigurationChangedException();
482 }
483 }
484
485 /**
486 * Detail configuration of Image Magick and Graphics Magick settings
487 * depending on main values.
488 *
489 * "Configuration presets" in install tool is not type safe, so value
490 * comparisons here are not type safe too, to not trigger changes to
491 * LocalConfiguration again.
492 */
493 protected function setImageMagickDetailSettings()
494 {
495 $changedValues = [];
496 try {
497 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor');
498 } catch (MissingArrayPathException $e) {
499 $currentProcessorValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor');
500 }
501
502 try {
503 $currentProcessorMaskValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_allowTemporaryMasksAsPng');
504 } catch (MissingArrayPathException $e) {
505 $currentProcessorMaskValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_allowTemporaryMasksAsPng');
506 }
507
508 try {
509 $currentProcessorEffectsValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_effects');
510 } catch (MissingArrayPathException $e) {
511 $currentProcessorEffectsValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_effects');
512 }
513
514 if ((string)$currentProcessorValue !== '') {
515 if ($currentProcessorMaskValue != 0) {
516 $changedValues['GFX/processor_allowTemporaryMasksAsPng'] = 0;
517 }
518 if ($currentProcessorValue === 'GraphicsMagick') {
519 if ($currentProcessorEffectsValue != -1) {
520 $changedValues['GFX/processor_effects'] = -1;
521 }
522 }
523 }
524 if (!empty($changedValues)) {
525 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
526 $this->throwConfigurationChangedException();
527 }
528 }
529
530 /**
531 * Migrate the definition of the image processor from the configuration value
532 * im_version_5 to the setting processor.
533 */
534 protected function migrateImageProcessorSetting()
535 {
536 $changedSettings = [];
537 $settingsToRename = [
538 'GFX/im' => 'GFX/processor_enabled',
539 'GFX/im_version_5' => 'GFX/processor',
540 'GFX/im_v5effects' => 'GFX/processor_effects',
541 'GFX/im_path' => 'GFX/processor_path',
542 'GFX/im_path_lzw' => 'GFX/processor_path_lzw',
543 'GFX/im_mask_temp_ext_gif' => 'GFX/processor_allowTemporaryMasksAsPng',
544 'GFX/im_noScaleUp' => 'GFX/processor_allowUpscaling',
545 'GFX/im_noFramePrepended' => 'GFX/processor_allowFrameSelection',
546 'GFX/im_stripProfileCommand' => 'GFX/processor_stripColorProfileCommand',
547 'GFX/im_useStripProfileByDefault' => 'GFX/processor_stripColorProfileByDefault',
548 'GFX/colorspace' => 'GFX/processor_colorspace',
549 ];
550
551 foreach ($settingsToRename as $oldPath => $newPath) {
552 try {
553 $value = $this->configurationManager->getLocalConfigurationValueByPath($oldPath);
554 $this->configurationManager->setLocalConfigurationValueByPath($newPath, $value);
555 $changedSettings[$oldPath] = true;
556 } catch (MissingArrayPathException $e) {
557 // If an exception is thrown, the value is not set in LocalConfiguration
558 $changedSettings[$oldPath] = false;
559 }
560 }
561
562 if (!empty($changedSettings['GFX/im_version_5'])) {
563 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_version_5');
564 $newProcessorValue = $currentProcessorValue === 'gm' ? 'GraphicsMagick' : 'ImageMagick';
565 $this->configurationManager->setLocalConfigurationValueByPath('GFX/processor', $newProcessorValue);
566 }
567
568 if (!empty($changedSettings['GFX/im_noScaleUp'])) {
569 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_noScaleUp');
570 $newProcessorValue = !$currentProcessorValue;
571 $this->configurationManager->setLocalConfigurationValueByPath(
572 'GFX/processor_allowUpscaling',
573 $newProcessorValue
574 );
575 }
576
577 if (!empty($changedSettings['GFX/im_noFramePrepended'])) {
578 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_noFramePrepended');
579 $newProcessorValue = !$currentProcessorValue;
580 $this->configurationManager->setLocalConfigurationValueByPath(
581 'GFX/processor_allowFrameSelection',
582 $newProcessorValue
583 );
584 }
585
586 if (!empty($changedSettings['GFX/im_mask_temp_ext_gif'])) {
587 $currentProcessorValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/im_mask_temp_ext_gif');
588 $newProcessorValue = !$currentProcessorValue;
589 $this->configurationManager->setLocalConfigurationValueByPath(
590 'GFX/processor_allowTemporaryMasksAsPng',
591 $newProcessorValue
592 );
593 }
594
595 if (!empty(array_filter($changedSettings))) {
596 $this->configurationManager->removeLocalConfigurationKeysByPath(array_keys($changedSettings));
597 $this->throwConfigurationChangedException();
598 }
599 }
600
601 /**
602 * Throw exception after configuration change to trigger a redirect.
603 *
604 * @throws ConfigurationChangedException
605 */
606 protected function throwConfigurationChangedException()
607 {
608 throw new ConfigurationChangedException(
609 'Configuration updated, reload needed',
610 1379024938
611 );
612 }
613
614 /**
615 * Migrate the configuration value thumbnails_png to a boolean value.
616 */
617 protected function migrateThumbnailsPngSetting()
618 {
619 $changedValues = [];
620 try {
621 $currentThumbnailsPngValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/thumbnails_png');
622 } catch (MissingArrayPathException $e) {
623 $currentThumbnailsPngValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/thumbnails_png');
624 }
625
626 if (is_int($currentThumbnailsPngValue) && $currentThumbnailsPngValue > 0) {
627 $changedValues['GFX/thumbnails_png'] = true;
628 }
629 if (!empty($changedValues)) {
630 $this->configurationManager->setLocalConfigurationValuesByPathValuePairs($changedValues);
631 $this->throwConfigurationChangedException();
632 }
633 }
634
635 /**
636 * Migrate the configuration setting BE/lockSSL to boolean if set in the LocalConfiguration.php file
637 */
638 protected function migrateLockSslSetting()
639 {
640 try {
641 $currentOption = $this->configurationManager->getLocalConfigurationValueByPath('BE/lockSSL');
642 // check if the current option is an integer/string and if it is active
643 if (!is_bool($currentOption) && (int)$currentOption > 0) {
644 $this->configurationManager->setLocalConfigurationValueByPath('BE/lockSSL', true);
645 $this->throwConfigurationChangedException();
646 }
647 } catch (MissingArrayPathException $e) {
648 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
649 }
650 }
651
652 /**
653 * Move the database connection settings to a "Default" connection
654 */
655 protected function migrateDatabaseConnectionSettings()
656 {
657 $confManager = $this->configurationManager;
658
659 $newSettings = [];
660 $removeSettings = [];
661
662 try {
663 $value = $confManager->getLocalConfigurationValueByPath('DB/username');
664 $removeSettings[] = 'DB/username';
665 $newSettings['DB/Connections/Default/user'] = $value;
666 } catch (MissingArrayPathException $e) {
667 // Old setting does not exist, do nothing
668 }
669
670 try {
671 $value = $confManager->getLocalConfigurationValueByPath('DB/password');
672 $removeSettings[] = 'DB/password';
673 $newSettings['DB/Connections/Default/password'] = $value;
674 } catch (MissingArrayPathException $e) {
675 // Old setting does not exist, do nothing
676 }
677
678 try {
679 $value = $confManager->getLocalConfigurationValueByPath('DB/host');
680 $removeSettings[] = 'DB/host';
681 $newSettings['DB/Connections/Default/host'] = $value;
682 } catch (MissingArrayPathException $e) {
683 // Old setting does not exist, do nothing
684 }
685
686 try {
687 $value = $confManager->getLocalConfigurationValueByPath('DB/port');
688 $removeSettings[] = 'DB/port';
689 $newSettings['DB/Connections/Default/port'] = $value;
690 } catch (MissingArrayPathException $e) {
691 // Old setting does not exist, do nothing
692 }
693
694 try {
695 $value = $confManager->getLocalConfigurationValueByPath('DB/socket');
696 $removeSettings[] = 'DB/socket';
697 // Remove empty socket connects
698 if (!empty($value)) {
699 $newSettings['DB/Connections/Default/unix_socket'] = $value;
700 }
701 } catch (MissingArrayPathException $e) {
702 // Old setting does not exist, do nothing
703 }
704
705 try {
706 $value = $confManager->getLocalConfigurationValueByPath('DB/database');
707 $removeSettings[] = 'DB/database';
708 $newSettings['DB/Connections/Default/dbname'] = $value;
709 } catch (MissingArrayPathException $e) {
710 // Old setting does not exist, do nothing
711 }
712
713 try {
714 $value = (bool)$confManager->getLocalConfigurationValueByPath('SYS/dbClientCompress');
715 $removeSettings[] = 'SYS/dbClientCompress';
716 if ($value) {
717 $newSettings['DB/Connections/Default/driverOptions'] = [
718 'flags' => MYSQLI_CLIENT_COMPRESS,
719 ];
720 }
721 } catch (MissingArrayPathException $e) {
722 // Old setting does not exist, do nothing
723 }
724
725 try {
726 $value = (bool)$confManager->getLocalConfigurationValueByPath('SYS/no_pconnect');
727 $removeSettings[] = 'SYS/no_pconnect';
728 if (!$value) {
729 $newSettings['DB/Connections/Default/persistentConnection'] = true;
730 }
731 } catch (MissingArrayPathException $e) {
732 // Old setting does not exist, do nothing
733 }
734
735 try {
736 $value = $confManager->getLocalConfigurationValueByPath('SYS/setDBinit');
737 $removeSettings[] = 'SYS/setDBinit';
738 $newSettings['DB/Connections/Default/initCommands'] = $value;
739 } catch (MissingArrayPathException $e) {
740 // Old setting does not exist, do nothing
741 }
742
743 try {
744 $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/charset');
745 } catch (MissingArrayPathException $e) {
746 // If there is no charset option yet, add it.
747 $newSettings['DB/Connections/Default/charset'] = 'utf8';
748 }
749
750 try {
751 $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driver');
752 } catch (MissingArrayPathException $e) {
753 // Use the mysqli driver by default if no value has been provided yet
754 $newSettings['DB/Connections/Default/driver'] = 'mysqli';
755 }
756
757 // Add new settings and remove old ones
758 if (!empty($newSettings)) {
759 $confManager->setLocalConfigurationValuesByPathValuePairs($newSettings);
760 }
761 if (!empty($removeSettings)) {
762 $confManager->removeLocalConfigurationKeysByPath($removeSettings);
763 }
764
765 // Throw redirect if something was changed
766 if (!empty($newSettings) || !empty($removeSettings)) {
767 $this->throwConfigurationChangedException();
768 }
769 }
770
771 /**
772 * Migrate the configuration setting DB/Connections/Default/charset to 'utf8' as
773 * 'utf-8' is not supported by all MySQL versions.
774 */
775 protected function migrateDatabaseConnectionCharset()
776 {
777 $confManager = $this->configurationManager;
778 try {
779 $driver = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driver');
780 $charset = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/charset');
781 if (in_array($driver, ['mysqli', 'pdo_mysql', 'drizzle_pdo_mysql'], true) && $charset === 'utf-8') {
782 $confManager->setLocalConfigurationValueByPath('DB/Connections/Default/charset', 'utf8');
783 $this->throwConfigurationChangedException();
784 }
785 } catch (MissingArrayPathException $e) {
786 // no incompatible charset configuration found, so nothing needs to be modified
787 }
788 }
789
790 /**
791 * Migrate the configuration setting DB/Connections/Default/driverOptions to array type.
792 */
793 protected function migrateDatabaseDriverOptions()
794 {
795 $confManager = $this->configurationManager;
796 try {
797 $options = $confManager->getLocalConfigurationValueByPath('DB/Connections/Default/driverOptions');
798 if (!is_array($options)) {
799 $confManager->setLocalConfigurationValueByPath(
800 'DB/Connections/Default/driverOptions',
801 ['flags' => (int)$options]
802 );
803 }
804 } catch (MissingArrayPathException $e) {
805 // no driver options found, nothing needs to be modified
806 }
807 }
808
809 /**
810 * Migrate the configuration setting BE/lang/debug if set in the LocalConfiguration.php file
811 */
812 protected function migrateLangDebug()
813 {
814 $confManager = $this->configurationManager;
815 try {
816 $currentOption = $confManager->getLocalConfigurationValueByPath('BE/lang/debug');
817 // check if the current option is set and boolean
818 if (isset($currentOption) && is_bool($currentOption)) {
819 $confManager->setLocalConfigurationValueByPath('BE/languageDebug', $currentOption);
820 }
821 } catch (MissingArrayPathException $e) {
822 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
823 }
824 }
825
826 /**
827 * Migrate single cache hash related options under "FE" into "FE/cacheHash"
828 */
829 protected function migrateCacheHashOptions()
830 {
831 $confManager = $this->configurationManager;
832 $removeSettings = [];
833 $newSettings = [];
834
835 try {
836 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashOnlyForParameters');
837 $removeSettings[] = 'FE/cHashOnlyForParameters';
838 $newSettings['FE/cacheHash/cachedParametersWhiteList'] = GeneralUtility::trimExplode(',', $value, true);
839 } catch (MissingArrayPathException $e) {
840 // Migration done already
841 }
842
843 try {
844 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashExcludedParameters');
845 $removeSettings[] = 'FE/cHashExcludedParameters';
846 $newSettings['FE/cacheHash/excludedParameters'] = GeneralUtility::trimExplode(',', $value, true);
847 } catch (MissingArrayPathException $e) {
848 // Migration done already
849 }
850
851 try {
852 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashRequiredParameters');
853 $removeSettings[] = 'FE/cHashRequiredParameters';
854 $newSettings['FE/cacheHash/requireCacheHashPresenceParameters'] = GeneralUtility::trimExplode(',', $value, true);
855 } catch (MissingArrayPathException $e) {
856 // Migration done already
857 }
858
859 try {
860 $value = $confManager->getLocalConfigurationValueByPath('FE/cHashExcludedParametersIfEmpty');
861 $removeSettings[] = 'FE/cHashExcludedParametersIfEmpty';
862 if (trim($value) === '*') {
863 $newSettings['FE/cacheHash/excludeAllEmptyParameters'] = true;
864 } else {
865 $newSettings['FE/cacheHash/excludedParametersIfEmpty'] = GeneralUtility::trimExplode(',', $value, true);
866 }
867 } catch (MissingArrayPathException $e) {
868 // Migration done already
869 }
870
871 // Add new settings and remove old ones
872 if (!empty($newSettings)) {
873 $confManager->setLocalConfigurationValuesByPathValuePairs($newSettings);
874 }
875 if (!empty($removeSettings)) {
876 $confManager->removeLocalConfigurationKeysByPath($removeSettings);
877 }
878
879 // Throw redirect if something was changed
880 if (!empty($newSettings) || !empty($removeSettings)) {
881 $this->throwConfigurationChangedException();
882 }
883 }
884
885 /**
886 * Migrate SYS/exceptionalErrors to not contain E_USER_DEPRECATED
887 */
888 protected function migrateExceptionErrors()
889 {
890 $confManager = $this->configurationManager;
891 try {
892 $currentOption = (int)$confManager->getLocalConfigurationValueByPath('SYS/exceptionalErrors');
893 // make sure E_USER_DEPRECATED is not part of the exceptionalErrors
894 if ($currentOption & E_USER_DEPRECATED) {
895 $confManager->setLocalConfigurationValueByPath('SYS/exceptionalErrors', $currentOption & ~E_USER_DEPRECATED);
896 }
897 } catch (MissingArrayPathException $e) {
898 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
899 }
900 }
901
902 /**
903 * Migrate SYS/displayErrors to not contain 2
904 */
905 protected function migrateDisplayErrorsSetting()
906 {
907 $confManager = $this->configurationManager;
908 try {
909 $currentOption = (int)$confManager->getLocalConfigurationValueByPath('SYS/displayErrors');
910 // make sure displayErrors is set to 2
911 if ($currentOption === 2) {
912 $confManager->setLocalConfigurationValueByPath('SYS/displayErrors', -1);
913 }
914 } catch (MissingArrayPathException $e) {
915 // no change inside the LocalConfiguration.php found, so nothing needs to be modified
916 }
917 }
918 }