You are here

function drupal_rewrite_settings in Drupal 9

Same name and namespace in other branches
  1. 8 core/includes/install.inc \drupal_rewrite_settings()
  2. 5 includes/install.inc \drupal_rewrite_settings()
  3. 6 includes/install.inc \drupal_rewrite_settings()
  4. 7 includes/install.inc \drupal_rewrite_settings()

Replaces values in settings.php with values in the submitted array.

This function replaces values in place if possible, even for multidimensional arrays. This way the old settings do not linger, overridden and also the doxygen on a value remains where it should be.

Parameters

$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.

$settings['settings']['config_sync_directory'] = (object) array(
  'value' => 'config_hash/sync',
  'required' => TRUE,
);

gets dumped as:

$settings['config_sync_directory'] = 'config_hash/sync';
3 calls to drupal_rewrite_settings()
FunctionalTestSetupTrait::writeSettings in core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php
Rewrites the settings.php file of the test site.
SettingsRewriteTest::testDrupalRewriteSettings in core/tests/Drupal/KernelTests/Core/Site/SettingsRewriteTest.php
Tests the drupal_rewrite_settings() function.
SiteSettingsForm::submitForm in core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php
Form submission handler.

File

core/includes/install.inc, line 257
API functions for installing modules and themes.

Code

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)) {
        list($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, $value)) {
              $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.");
  }
}