diff options
author | xjm <xjm@65776.no-reply.drupal.org> | 2023-01-07 15:32:44 -0600 |
---|---|---|
committer | xjm <xjm@65776.no-reply.drupal.org> | 2023-01-07 15:32:44 -0600 |
commit | 4d9b40b01e2c02e5e53b69102c07b3df31353d4e (patch) | |
tree | a7719d74cae1c625db00e898dcc30a0b56654cff | |
parent | 8b49c009d13194ad6fc00f2a5be50e483b110674 (diff) | |
download | drupal-4d9b40b01e2c02e5e53b69102c07b3df31353d4e.tar.gz drupal-4d9b40b01e2c02e5e53b69102c07b3df31353d4e.zip |
Issue #3244570 by voleger, xjm, alexpott, longwave, andypost: Deprecate drupal_rewrite_settings()
-rw-r--r-- | core/includes/install.inc | 199 | ||||
-rw-r--r-- | core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php | 3 | ||||
-rw-r--r-- | core/lib/Drupal/Core/Site/SettingsEditor.php | 305 | ||||
-rw-r--r-- | core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php | 7 | ||||
-rw-r--r-- | core/phpstan-baseline.neon | 20 | ||||
-rw-r--r-- | core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php | 4 | ||||
-rw-r--r-- | core/tests/Drupal/KernelTests/Core/Site/LegacySettingsRewriteTest.php | 131 | ||||
-rw-r--r-- | core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php | 11 | ||||
-rw-r--r-- | core/tests/Drupal/Tests/BrowserTestBase.php | 4 |
9 files changed, 516 insertions, 168 deletions
diff --git a/core/includes/install.inc b/core/includes/install.inc index c8dd224cab5..588855a3dc9 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -5,14 +5,13 @@ * API functions for installing modules and themes. */ -use Drupal\Component\Utility\OpCodeCache; use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Database\Database; use Drupal\Core\Extension\Dependency; use Drupal\Core\Extension\ExtensionDiscovery; use Drupal\Core\Installer\InstallerKernel; -use Drupal\Core\Site\Settings; +use Drupal\Core\Site\SettingsEditor; use Symfony\Component\HttpFoundation\RedirectResponse; /** @@ -254,154 +253,20 @@ function drupal_get_database_types() { * @code * $settings['config_sync_directory'] = 'config_hash/sync' * @endcode + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. Note $settings_file argument becomes + * required and the first argument of the method. + * + * @see https://www.drupal.org/node/3244583 + * @see \Drupal\Core\Site\SettingsEditor::rewrite() */ function drupal_rewrite_settings($settings = [], $settings_file = NULL) { - if (!isset($settings_file)) { - $settings_file = \Drupal::getContainer()->getParameter('site.path') . '/settings.php'; - } - // Build list of setting names and insert the values into the global namespace. - $variable_names = []; - $settings_settings = []; - foreach ($settings as $setting => $data) { - if ($setting != 'settings') { - _drupal_rewrite_settings_global($GLOBALS[$setting], $data); - } - else { - _drupal_rewrite_settings_global($settings_settings, $data); - } - $variable_names['$' . $setting] = $setting; - } - $contents = file_get_contents($settings_file); - if ($contents !== FALSE) { - // Initialize the contents for the settings.php file if it is empty. - if (trim($contents) === '') { - $contents = "<?php\n"; - } - // Step through each token in settings.php and replace any variables that - // are in the passed-in array. - $buffer = ''; - $state = 'default'; - foreach (token_get_all($contents) as $token) { - if (is_array($token)) { - [$type, $value] = $token; - } - else { - $type = -1; - $value = $token; - } - // Do not operate on whitespace. - if (!in_array($type, [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT])) { - switch ($state) { - case 'default': - if ($type === T_VARIABLE && isset($variable_names[$value])) { - // This will be necessary to unset the dumped variable. - $parent = &$settings; - // This is the current index in parent. - $index = $variable_names[$value]; - // This will be necessary for descending into the array. - $current = &$parent[$index]; - $state = 'candidate_left'; - } - break; - - case 'candidate_left': - if ($value == '[') { - $state = 'array_index'; - } - if ($value == '=') { - $state = 'candidate_right'; - } - break; - - case 'array_index': - if (_drupal_rewrite_settings_is_array_index($type)) { - $index = trim($value, '\'"'); - $state = 'right_bracket'; - } - else { - // $a[foo()] or $a[$bar] or something like that. - throw new Exception('invalid array index'); - } - break; - - case 'right_bracket': - if ($value == ']') { - if (isset($current[$index])) { - // If the new settings has this index, descend into it. - $parent = &$current; - $current = &$parent[$index]; - $state = 'candidate_left'; - } - else { - // Otherwise, jump back to the default state. - $state = 'wait_for_semicolon'; - } - } - else { - // $a[1 + 2]. - throw new Exception('] expected'); - } - break; - - case 'candidate_right': - if (_drupal_rewrite_settings_is_simple($type, $value)) { - $value = _drupal_rewrite_settings_dump_one($current); - // Unsetting $current would not affect $settings at all. - unset($parent[$index]); - // Skip the semicolon because _drupal_rewrite_settings_dump_one() added one. - $state = 'semicolon_skip'; - } - else { - $state = 'wait_for_semicolon'; - } - break; - - case 'wait_for_semicolon': - if ($value == ';') { - $state = 'default'; - } - break; - - case 'semicolon_skip': - if ($value == ';') { - $value = ''; - $state = 'default'; - } - else { - // If the expression was $a = 1 + 2; then we replaced 1 and - // the + is unexpected. - throw new Exception('Unexpected token after replacing value.'); - } - break; - } - } - $buffer .= $value; - } - foreach ($settings as $name => $setting) { - $buffer .= _drupal_rewrite_settings_dump($setting, '$' . $name); - } - - // Write the new settings file. - if (file_put_contents($settings_file, $buffer) === FALSE) { - throw new Exception("Failed to modify '$settings_file'. Verify the file permissions."); - } - else { - // In case any $settings variables were written, import them into the - // Settings singleton. - if (!empty($settings_settings)) { - $old_settings = Settings::getAll(); - new Settings($settings_settings + $old_settings); - } - // The existing settings.php file might have been included already. In - // case an opcode cache is enabled, the rewritten contents of the file - // will not be reflected in this process. Ensure to invalidate the file - // in case an opcode cache is enabled. - OpCodeCache::invalidate(DRUPAL_ROOT . '/' . $settings_file); - } - } - else { - throw new Exception("Failed to open '$settings_file'. Verify the file permissions."); - } + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. The order of the arguments has also changed: $settings_file is now required and is the first argument of the method. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); + SettingsEditor::rewrite( + $settings_file ?? \Drupal::getContainer()->getParameter('site.path') . '/settings.php', + $settings + ); } /** @@ -417,9 +282,16 @@ function drupal_rewrite_settings($settings = [], $settings_file = NULL) { * @return bool * TRUE if this token represents a scalar or NULL. * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. As internal API, + * _drupal_rewrite_settings_is_simple() may also be removed in a minor + * release. + * + * @see https://www.drupal.org/node/3244583 * @see token_name() */ function _drupal_rewrite_settings_is_simple($type, $value) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. As internal API, ' . __FUNCTION__ . '() may also be removed in a minor release. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); $is_integer = $type == T_LNUMBER; $is_float = $type == T_DNUMBER; $is_string = $type == T_CONSTANT_ENCAPSED_STRING; @@ -439,9 +311,16 @@ function _drupal_rewrite_settings_is_simple($type, $value) { * @return bool * TRUE if this token represents a number or a string. * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. As internal API, + * _drupal_rewrite_settings_is_array_index() may also be removed in a minor + * release. + * + * @see https://www.drupal.org/node/3244583 * @see token_name() */ function _drupal_rewrite_settings_is_array_index($type) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. As internal API, ' . __FUNCTION__ . '() may also be removed in a minor release. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); $is_integer = $type == T_LNUMBER; $is_float = $type == T_DNUMBER; $is_string = $type == T_CONSTANT_ENCAPSED_STRING; @@ -457,8 +336,16 @@ function _drupal_rewrite_settings_is_array_index($type) { * A reference to a nested index in $GLOBALS. * @param array|object $variable * The nested value of the setting being copied. + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. As internal API, + * _drupal_rewrite_settings_global() may also be removed in a minor + * release. + * + * @see https://www.drupal.org/node/3244583 */ function _drupal_rewrite_settings_global(&$ref, $variable) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. As internal API, ' . __FUNCTION__ . '() may also be removed in a minor release. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); if (is_object($variable)) { $ref = $variable->value; } @@ -482,8 +369,16 @@ function _drupal_rewrite_settings_global(&$ref, $variable) { * @return string * A string containing valid PHP code of the variable suitable for placing * into settings.php. + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. As internal API, + * _drupal_rewrite_settings_dump() may also be removed in a minor + * release. + * + * @see https://www.drupal.org/node/3244583 */ function _drupal_rewrite_settings_dump($variable, $variable_name) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. As internal API, ' . __FUNCTION__ . '() may also be removed in a minor release. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); $return = ''; if (is_object($variable)) { if (!empty($variable->required)) { @@ -513,8 +408,16 @@ function _drupal_rewrite_settings_dump($variable, $variable_name) { * @return string * A string containing valid PHP code of the variable suitable for placing * into settings.php. + * + * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use + * SettingsEditor::rewrite() instead. As internal API, + * _drupal_rewrite_settings_dump_one() may also be removed in a minor + * release. + * + * @see https://www.drupal.org/node/3244583 */ function _drupal_rewrite_settings_dump_one(\stdClass $variable, $prefix = '', $suffix = '') { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. As internal API, ' . __FUNCTION__ . '() may also be removed in a minor release. See https://www.drupal.org/node/3244583', E_USER_DEPRECATED); $return = $prefix . var_export($variable->value, TRUE) . ';'; if (!empty($variable->comment)) { $return .= ' // ' . $variable->comment; diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index dc265471222..0f1f25bb914 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\RendererInterface; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\SettingsEditor; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -264,7 +265,7 @@ class SiteSettingsForm extends FormBase { ]; } - drupal_rewrite_settings($settings); + SettingsEditor::rewrite($this->sitePath . '/settings.php', $settings); // Indicate that the settings file has been verified, and check the database // for the last completed task, now that we have a valid connection. This diff --git a/core/lib/Drupal/Core/Site/SettingsEditor.php b/core/lib/Drupal/Core/Site/SettingsEditor.php new file mode 100644 index 00000000000..e9a8c4c99f0 --- /dev/null +++ b/core/lib/Drupal/Core/Site/SettingsEditor.php @@ -0,0 +1,305 @@ +<?php + +namespace Drupal\Core\Site; + +use Drupal\Component\Utility\OpCodeCache; + +/** + * Generates settings.php files for Drupal installations. + */ +final class SettingsEditor { + + /** + * This class should not be instantiated. + * + * Use a static ::rewrite() method call instead. + * + * @see \Drupal\Core\Site\SettingsEditor::rewrite() + */ + private function __construct() {} + + /** + * Replaces values in settings.php with values in the submitted array. + * + * This method rewrites values in place if possible, even for + * multidimensional arrays. This helps ensure that the documentation remains + * attached to the correct settings and that old, overridden values do not + * clutter up the file. + * + * @code + * $settings['settings']['config_sync_directory'] = (object) array( + * 'value' => 'config_hash/sync', + * 'required' => TRUE, + * ); + * @endcode + * gets dumped as: + * @code + * $settings['config_sync_directory'] = 'config_hash/sync' + * @endcode + * + * @param string $settings_file + * Path to the settings file relative to the DRUPAL_ROOT directory. + * @param array $settings + * An array of settings that need to be updated. Multidimensional arrays + * are dumped up to a stdClass object. The object can have value, required + * and comment properties. + * + * @throws \Exception + */ + public static function rewrite(string $settings_file, array $settings = []): void { + // Build list of setting names and insert the values into the global + // namespace. + $variable_names = []; + $settings_settings = []; + foreach ($settings as $setting => $data) { + if ($setting !== 'settings') { + self::setGlobal($GLOBALS[$setting], $data); + } + else { + self::setGlobal($settings_settings, $data); + } + $variable_names['$' . $setting] = $setting; + } + $contents = file_get_contents($settings_file); + if ($contents !== FALSE) { + // Initialize the contents for the settings.php file if it is empty. + if (trim($contents) === '') { + $contents = "<?php\n"; + } + // Step through each token in settings.php and replace any variables that + // are in the passed-in array. + $buffer = ''; + $state = 'default'; + foreach (token_get_all($contents) as $token) { + if (is_array($token)) { + [$type, $value] = $token; + } + else { + $type = -1; + $value = $token; + } + // Do not operate on whitespace. + if (!in_array($type, [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], TRUE)) { + switch ($state) { + case 'default': + if ($type === T_VARIABLE && isset($variable_names[$value])) { + // This will be necessary to unset the dumped variable. + $parent = &$settings; + // This is the current index in parent. + $index = $variable_names[$value]; + // This will be necessary for descending into the array. + $current = &$parent[$index]; + $state = 'candidate_left'; + } + break; + + case 'candidate_left': + if ($value === '[') { + $state = 'array_index'; + } + if ($value === '=') { + $state = 'candidate_right'; + } + break; + + case 'array_index': + if (self::isArrayIndex($type)) { + $index = trim($value, '\'"'); + $state = 'right_bracket'; + } + else { + // $a[foo()] or $a[$bar] or something like that. + throw new \Exception('invalid array index'); + } + break; + + case 'right_bracket': + if ($value === ']') { + if (isset($current[$index])) { + // If the new settings has this index, descend into it. + $parent = &$current; + $current = &$parent[$index]; + $state = 'candidate_left'; + } + else { + // Otherwise, jump back to the default state. + $state = 'wait_for_semicolon'; + } + } + else { + // $a[1 + 2]. + throw new \Exception('] expected'); + } + break; + + case 'candidate_right': + if (self::isSimple($type, $value)) { + $value = self::exportSingleSettingToPhp($current); + // Unsetting $current would not affect $settings at all. + unset($parent[$index]); + // Skip the semicolon because self::dumpOne() added one. + $state = 'semicolon_skip'; + } + else { + $state = 'wait_for_semicolon'; + } + break; + + case 'wait_for_semicolon': + if ($value === ';') { + $state = 'default'; + } + break; + + case 'semicolon_skip': + if ($value === ';') { + $value = ''; + $state = 'default'; + } + else { + // If the expression was $a = 1 + 2; then we replaced 1 and + // the + is unexpected. + throw new \Exception('Unexpected token after replacing value.'); + } + break; + } + } + $buffer .= $value; + } + foreach ($settings as $name => $setting) { + $buffer .= self::exportSettingsToPhp($setting, '$' . $name); + } + + // Write the new settings file. + if (file_put_contents($settings_file, $buffer) === FALSE) { + throw new \Exception("Failed to modify '$settings_file'. Verify the file permissions."); + } + // In case any $settings variables were written, import them into the + // Settings singleton. + if (!empty($settings_settings)) { + $old_settings = Settings::getAll(); + new Settings($settings_settings + $old_settings); + } + // The existing settings.php file might have been included already. In + // case an opcode cache is enabled, the rewritten contents of the file + // will not be reflected in this process. Ensure to invalidate the file + // in case an opcode cache is enabled. + OpCodeCache::invalidate(DRUPAL_ROOT . '/' . $settings_file); + } + else { + throw new \Exception("Failed to open '$settings_file'. Verify the file permissions."); + } + } + + /** + * Checks whether the given token represents a scalar or NULL. + * + * @param int $type + * The token type. + * @param string $value + * The value of the token. + * + * @return bool + * TRUE if this token represents a scalar or NULL. + * + * @see token_name() + */ + private static function isSimple(int $type, string $value): bool { + $is_integer = $type === T_LNUMBER; + $is_float = $type === T_DNUMBER; + $is_string = $type === T_CONSTANT_ENCAPSED_STRING; + $is_boolean_or_null = $type === T_STRING && in_array( + strtoupper($value), + ['TRUE', 'FALSE', 'NULL'] + ); + return $is_integer || $is_float || $is_string || $is_boolean_or_null; + } + + /** + * Checks whether the token is a valid array index (a number or string). + * + * @param int $type + * The token type. + * + * @return bool + * TRUE if this token represents a number or a string. + * + * @see token_name() + */ + private static function isArrayIndex(int $type): bool { + $is_integer = $type === T_LNUMBER; + $is_float = $type === T_DNUMBER; + $is_string = $type === T_CONSTANT_ENCAPSED_STRING; + return $is_integer || $is_float || $is_string; + } + + /** + * Makes the given setting global. + * + * @param mixed $ref + * A reference to a nested index in $GLOBALS. + * @param array|object $variable + * The nested value of the setting being copied. + */ + private static function setGlobal(mixed &$ref, array|object $variable): void { + if (is_object($variable)) { + $ref = $variable->value; + } + else { + foreach ($variable as $k => $v) { + self::setGlobal($ref[$k], $v); + } + } + } + + /** + * Recursively exports one or more settings to a valid PHP string. + * + * @param array|object $variable + * The container for variable values. + * @param string $variable_name + * Name of variable. + * + * @return string + * A string containing valid PHP code of the variable suitable for placing + * into settings.php. + */ + private static function exportSettingsToPhp(array|object $variable, string $variable_name): string { + $return = ''; + if (is_object($variable)) { + if (!empty($variable->required)) { + $return .= self::exportSingleSettingToPhp($variable, "$variable_name = ", "\n"); + } + } + else { + foreach ($variable as $k => $v) { + $return .= self::exportSettingsToPhp($v, $variable_name . "['" . $k . "']"); + } + } + return $return; + } + + /** + * Exports the value of a value property and adds the comment if it exists. + * + * @param object $variable + * A stdClass object with at least a value property. + * @param string $prefix + * A string to prepend to the variable's value. + * @param string $suffix + * A string to append to the variable's value. + * + * @return string + * A string containing valid PHP code of the variable suitable for placing + * into settings.php. + */ + private static function exportSingleSettingToPhp(object $variable, string $prefix = '', string $suffix = ''): string { + $return = $prefix . var_export($variable->value, TRUE) . ';'; + if (!empty($variable->comment)) { + $return .= ' // ' . $variable->comment; + } + $return .= $suffix; + return $return; + } + +} diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 5d37d5c8adb..15a1ee80de8 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -16,6 +16,7 @@ use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Serialization\Yaml; use Drupal\Core\Session\UserSession; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\SettingsEditor; use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\Tests\SessionTestTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -152,9 +153,9 @@ trait FunctionalTestSetupTrait { * * @param array $settings * An array of settings to write out, in the format expected by - * drupal_rewrite_settings(). + * SettingsEditor::rewrite(). * - * @see drupal_rewrite_settings() + * @see \Drupal\Core\Site\SettingsEditor::rewrite() */ protected function writeSettings(array $settings) { include_once DRUPAL_ROOT . '/core/includes/install.inc'; @@ -163,7 +164,7 @@ trait FunctionalTestSetupTrait { // whenever it is invoked. // Not using File API; a potential error must trigger a PHP warning. chmod($filename, 0666); - drupal_rewrite_settings($settings, $filename); + SettingsEditor::rewrite($filename, $settings); } /** diff --git a/core/phpstan-baseline.neon b/core/phpstan-baseline.neon index f26c4db4b38..16aba07556b 100644 --- a/core/phpstan-baseline.neon +++ b/core/phpstan-baseline.neon @@ -46,16 +46,6 @@ parameters: path: includes/install.core.inc - - message: "#^Variable \\$current might not be defined\\.$#" - count: 1 - path: includes/install.inc - - - - message: "#^Variable \\$index might not be defined\\.$#" - count: 3 - path: includes/install.inc - - - message: "#^Variable \\$items might not be defined\\.$#" count: 1 path: includes/theme.inc @@ -726,6 +716,16 @@ parameters: path: lib/Drupal/Core/Session/SessionManager.php - + message: "#^Variable \\$current might not be defined\\.$#" + count: 1 + path: lib/Drupal/Core/Site/SettingsEditor.php + + - + message: "#^Variable \\$index might not be defined\\.$#" + count: 3 + path: lib/Drupal/Core/Site/SettingsEditor.php + + - message: "#^Method Drupal\\\\Core\\\\Template\\\\AttributeValueBase\\:\\:render\\(\\) should return string but return statement is missing\\.$#" count: 1 path: lib/Drupal/Core/Template/AttributeValueBase.php diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index 5bf4918d084..6ec3919d6a8 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -28,7 +28,9 @@ abstract class InstallerTestBase extends BrowserTestBase { * * @var array * An array of settings to write out, in the format expected by - * drupal_rewrite_settings(). + * SettingsEditor::rewrite(). + * + * @see \Drupal\Core\Site\SettingsEditor::rewrite() */ protected $settings = []; diff --git a/core/tests/Drupal/KernelTests/Core/Site/LegacySettingsRewriteTest.php b/core/tests/Drupal/KernelTests/Core/Site/LegacySettingsRewriteTest.php new file mode 100644 index 00000000000..99666ced3b7 --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Site/LegacySettingsRewriteTest.php @@ -0,0 +1,131 @@ +<?php + +namespace Drupal\KernelTests\Core\Site; + +use Drupal\Core\Site\Settings; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests the drupal_rewrite_settings() function. + * + * @group system + * @group legacy + * @covers drupal_rewrite_settings() + */ +class LegacySettingsRewriteTest extends KernelTestBase { + + /** + * Tests the drupal_rewrite_settings() function. + */ + public function testDrupalRewriteSettings() { + include_once $this->root . '/core/includes/install.inc'; + $site_path = $this->container->getParameter('site.path'); + $tests = [ + [ + 'original' => '$no_index_value_scalar = TRUE;', + 'settings' => [ + 'no_index_value_scalar' => (object) [ + 'value' => FALSE, + 'comment' => 'comment', + ], + ], + 'expected' => '$no_index_value_scalar = false; // comment', + ], + [ + 'original' => '$no_index_value_scalar = TRUE;', + 'settings' => [ + 'no_index_value_foo' => [ + 'foo' => [ + 'value' => (object) [ + 'value' => NULL, + 'required' => TRUE, + 'comment' => 'comment', + ], + ], + ], + ], + 'expected' => <<<'EXPECTED' +$no_index_value_scalar = TRUE; +$no_index_value_foo['foo']['value'] = NULL; // comment +EXPECTED + ], + [ + 'original' => '$no_index_value_array = array("old" => "value");', + 'settings' => [ + 'no_index_value_array' => (object) [ + 'value' => FALSE, + 'required' => TRUE, + 'comment' => 'comment', + ], + ], + 'expected' => '$no_index_value_array = array("old" => "value"); +$no_index_value_array = false; // comment', + ], + [ + 'original' => '$has_index_value_scalar["foo"]["bar"] = NULL;', + 'settings' => [ + 'has_index_value_scalar' => [ + 'foo' => [ + 'bar' => (object) [ + 'value' => FALSE, + 'required' => TRUE, + 'comment' => 'comment', + ], + ], + ], + ], + 'expected' => '$has_index_value_scalar["foo"]["bar"] = false; // comment', + ], + [ + 'original' => '$has_index_value_scalar["foo"]["bar"] = "foo";', + 'settings' => [ + 'has_index_value_scalar' => [ + 'foo' => [ + 'value' => (object) [ + 'value' => ['value' => 2], + 'required' => TRUE, + 'comment' => 'comment', + ], + ], + ], + ], + 'expected' => <<<'EXPECTED' +$has_index_value_scalar["foo"]["bar"] = "foo"; +$has_index_value_scalar['foo']['value'] = array ( + 'value' => 2, +); // comment +EXPECTED + ], + ]; + foreach ($tests as $test) { + $filename = Settings::get('file_public_path', $site_path . '/files') . '/mock_settings.php'; + file_put_contents($filename, "<?php\n" . $test['original'] . "\n"); + $this->expectDeprecation('drupal_rewrite_settings() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. The order of the arguments has also changed: $settings_file is now required and is the first argument of the method. See https://www.drupal.org/node/3244583'); + drupal_rewrite_settings($test['settings'], $filename); + $this->assertEquals("<?php\n" . $test['expected'] . "\n", file_get_contents($filename)); + } + + // Test that <?php gets added to the start of an empty settings file. + // Set the array of settings that will be written to the file. + $test = [ + 'settings' => [ + 'no_index' => (object) [ + 'value' => TRUE, + 'required' => TRUE, + ], + ], + 'expected' => '$no_index = true;', + ]; + // Make an empty file. + $filename = Settings::get('file_public_path', $site_path . '/files') . '/mock_settings.php'; + file_put_contents($filename, ""); + + $this->expectDeprecation('drupal_rewrite_settings() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use SettingsEditor::rewrite() instead. The order of the arguments has also changed: $settings_file is now required and is the first argument of the method. See https://www.drupal.org/node/3244583'); + // Write the setting to the file. + drupal_rewrite_settings($test['settings'], $filename); + + // Check that the result is just the php opening tag and the settings. + $this->assertEquals("<?php\n" . $test['expected'] . "\n", file_get_contents($filename)); + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php b/core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php index bc521a22f15..3955205e86d 100644 --- a/core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php +++ b/core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php @@ -3,17 +3,20 @@ namespace Drupal\KernelTests\Core\Site; use Drupal\Core\Site\Settings; +use Drupal\Core\Site\SettingsEditor; use Drupal\KernelTests\KernelTestBase; /** - * Tests the drupal_rewrite_settings() function. + * Tests the SettingsEditor::rewrite() function. * * @group system + * + * @covers \Drupal\Core\Site\SettingsEditor::rewrite() */ class SettingsRewriteTest extends KernelTestBase { /** - * Tests the drupal_rewrite_settings() function. + * Tests the SettingsEditor::rewrite() function. */ public function testDrupalRewriteSettings() { include_once $this->root . '/core/includes/install.inc'; @@ -98,7 +101,7 @@ EXPECTED foreach ($tests as $test) { $filename = Settings::get('file_public_path', $site_path . '/files') . '/mock_settings.php'; file_put_contents($filename, "<?php\n" . $test['original'] . "\n"); - drupal_rewrite_settings($test['settings'], $filename); + SettingsEditor::rewrite($filename, $test['settings']); $this->assertEquals("<?php\n" . $test['expected'] . "\n", file_get_contents($filename)); } @@ -118,7 +121,7 @@ EXPECTED file_put_contents($filename, ""); // Write the setting to the file. - drupal_rewrite_settings($test['settings'], $filename); + SettingsEditor::rewrite($filename, $test['settings']); // Check that the result is just the php opening tag and the settings. $this->assertEquals("<?php\n" . $test['expected'] . "\n", file_get_contents($filename)); diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index cd75578c4eb..283cffc0b63 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -126,9 +126,11 @@ abstract class BrowserTestBase extends TestCase { protected $defaultTheme; /** - * An array of custom translations suitable for drupal_rewrite_settings(). + * An array of custom translations suitable for SettingsEditor::rewrite(). * * @var array + * + * @see \Drupal\Core\Site\SettingsEditor::rewrite() */ protected $customTranslations; |