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