Skip to content
Snippets Groups Projects
Unverified Commit 7d1f82b8 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3163226 by dww, jungle, alexpott, larowlan, longwave, cburschka: Add...

Issue #3163226 by dww, jungle, alexpott, larowlan, longwave, cburschka: Add the ability to deprecate a Settings name
parent 1d44c8eb
No related branches found
No related tags found
8 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!1012Issue #3226887: Hreflang on non-canonical content pages,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10,!596Issue #3046532: deleting an entity reference field, used in a contextual view, makes the whole site unrecoverable,!496Issue #2463967: Use .user.ini file for PHP settings,!144Issue #2666286: Clean up menu_ui to conform to Drupal coding standards,!16Draft: Resolve #2081585 "History storage",!13Resolve #2903456
......@@ -26,6 +26,19 @@ final class Settings {
*/
private static $instance = NULL;
/**
* Information about all deprecated settings, keyed by legacy settings name.
*
* Each entry should be an array that defines the following keys:
* - 'replacement': The new name for the setting.
* - 'message': The deprecation message to use for trigger_error().
*
* @var array
*
* @see self::handleDeprecations()
*/
private static $deprecatedSettings = [];
/**
* Constructor.
*
......@@ -84,6 +97,11 @@ public function __sleep() {
* The value of the setting, the provided default if not set.
*/
public static function get($name, $default = NULL) {
// If the caller is asking for the value of a deprecated setting, trigger a
// deprecation message about it.
if (isset(self::$deprecatedSettings[$name])) {
@trigger_error(self::$deprecatedSettings[$name]['message'], E_USER_DEPRECATED);
}
return isset(self::$instance->storage[$name]) ? self::$instance->storage[$name] : $default;
}
......@@ -122,6 +140,8 @@ public static function initialize($app_root, $site_path, &$class_loader) {
require $app_root . '/' . $site_path . '/settings.php';
}
self::handleDeprecations($settings);
// Initialize databases.
foreach ($databases as $key => $targets) {
foreach ($targets as $target => $info) {
......@@ -191,4 +211,28 @@ public static function getApcuPrefix($identifier, $root, $site_path = '') {
return 'drupal.' . $identifier . '.' . \Drupal::VERSION . '.' . static::get('deployment_identifier') . '.' . Crypt::hashBase64($root . '/' . $site_path);
}
/**
* Handle deprecated values in the site settings.
*
* @param array $settings
* The site settings.
*
* @see self::getDeprecatedSettings()
*/
private static function handleDeprecations(array &$settings): void {
foreach (self::$deprecatedSettings as $legacy => $deprecation) {
if (!empty($settings[$legacy])) {
@trigger_error($deprecation['message'], E_USER_DEPRECATED);
// Set the new key if needed.
if (!isset($settings[$deprecation['replacement']])) {
$settings[$deprecation['replacement']] = $settings[$legacy];
}
}
// Ensure that both keys have the same value.
if (isset($settings[$deprecation['replacement']])) {
$settings[$legacy] = $settings[$deprecation['replacement']];
}
}
}
}
......@@ -5,6 +5,7 @@
use Drupal\Core\Site\Settings;
use Drupal\Tests\Traits\ExpectDeprecationTrait;
use Drupal\Tests\UnitTestCase;
use org\bovigo\vfs\vfsStream;
/**
* @coversDefaultClass \Drupal\Core\Site\Settings
......@@ -150,4 +151,125 @@ public function testGetInstanceReflection() {
$settings->getInstance();
}
/**
* Tests deprecation messages and values when using fake deprecated settings.
*
* Note: Tests for real deprecated settings should not be added to this test
* or provider. This test is only for the general deprecated settings API
* itself.
*
* @param string[] $settings_config
* Array of settings to put in the settings.php file for testing.
* @param string $setting_name
* The name of the setting this case should use for Settings::get().
* @param string $expected_value
* The expected value of the setting.
* @param bool $expect_deprecation_message
* Should the case expect a deprecation message? Defaults to TRUE.
*
* @runInSeparateProcess
*
* @dataProvider providerTestFakeDeprecatedSettings
*
* @covers ::handleDeprecations
* @covers ::initialize
*
* @group legacy
*/
public function testFakeDeprecatedSettings(array $settings_config, string $setting_name, string $expected_value, bool $expect_deprecation_message = TRUE): void {
$settings_file_content = "<?php\n";
foreach ($settings_config as $name => $value) {
$settings_file_content .= "\$settings['$name'] = '$value';\n";
}
$class_loader = NULL;
$vfs_root = vfsStream::setup('root');
$sites_directory = vfsStream::newDirectory('sites')->at($vfs_root);
vfsStream::newFile('settings.php')
->at($sites_directory)
->setContent($settings_file_content);
// This is the deprecated setting used by all cases for this test method.
$deprecated_setting = [
'replacement' => 'happy_replacement',
'message' => 'The settings key "deprecated_legacy" is deprecated in drupal:9.1.0 and will be removed in drupal:10.0.0. Use "happy_replacement" instead. See https://www.drupal.org/node/3163226.',
];
$class = new \ReflectionClass(Settings::class);
$instance_property = $class->getProperty('deprecatedSettings');
$instance_property->setAccessible(TRUE);
$deprecated_settings = $instance_property->getValue();
$deprecated_settings['deprecated_legacy'] = $deprecated_setting;
$instance_property->setValue($deprecated_settings);
if ($expect_deprecation_message) {
$this->addExpectedDeprecationMessage($deprecated_setting['message']);
}
Settings::initialize(vfsStream::url('root'), 'sites', $class_loader);
$this->assertEquals($expected_value, Settings::get($setting_name));
}
/**
* Provides data for testFakeDeprecatedSettings().
*
* @return array
* Test case data.
*/
public function providerTestFakeDeprecatedSettings(): array {
$only_legacy = [
'deprecated_legacy' => 'old',
];
$only_replacement = [
'happy_replacement' => 'new',
];
$both_settings = [
'deprecated_legacy' => 'old',
'happy_replacement' => 'new',
];
return [
'Only legacy defined, get legacy' => [
$only_legacy,
'deprecated_legacy',
'old',
],
'Only legacy defined, get replacement' => [
$only_legacy,
'happy_replacement',
// Since the new setting isn't yet defined, use the old value.
'old',
// Since the old setting is there, we should see a deprecation message.
],
'Both legacy and replacement defined, get legacy' => [
$both_settings,
'deprecated_legacy',
// Since the replacement is already defined, that should be used.
'new',
],
'Both legacy and replacement defined, get replacement' => [
$both_settings,
'happy_replacement',
'new',
// Should see the deprecation, since the legacy setting is defined.
],
'Only replacement defined, get legacy' => [
$only_replacement,
'deprecated_legacy',
// Should get the new value.
'new',
// But we should see a deprecation message for accessing the old name.
],
'Only replacement defined, get replacement' => [
$only_replacement,
'happy_replacement',
// Should get the new value.
'new',
// No deprecation since the old name is neither used nor defined.
FALSE,
],
];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment