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