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