Currently there is easy way for installation profiles to write extra settings to settings.php. Calling drupal_rewrite_settings() overwrites any settings which are not set in the given $settings parameter with the defaults (because, obviously, the function reads only default.settings.php).

Right now, to prevent breakage, you have to always include $db_url (D6) / $databases (D7) and $db_prefix. Besides that, any custom settings the user has written in their settings.php file need to be included, or they will be lost in the rewrite.

I would like to be able to write more settings to settings.php in an installation profile, e.g. multilingual variables, proxy, site information, etc. without having to take care I miss any earlier written setting (automatic or by the user) -- so without having to add each possible setting to the $settings array.

Some possible ways to do this:

Read settings.php, then rewrite from default.settings.php
Basically that means drupal_rewrite_settings() would need to do this:

  1. Read settings.php line by line, find out which variables (just their names) have been set already.
  2. Those variables are still available as global in the runtime, so there's no need to read the values from the file; the variables and their current global values are set in an array (e.g. $existing_settings) with a similar format as the parameter $settings array (each item gets a 'value', 'required' and 'comment' entry). Each of these settings needs to have required set to TRUE so they don't go lost if they don't exist in defaults.settings.php
  3. $settings and $existing_settings are merges, such that settings that if a setting appears in both arrays the one from the parameter ($settings) is written. A simple array_merge should do this.
  4. Write out the variables as it's currently done, basing off the defaults.settings.php. Since all previously set variables are set as required (by default), they will always be rewritten to the new settings.php.

Steps 2 and 3 could be merged in one, by just (immediately) adding non-existing settings found in settings.php to $settings.

The hard step would be step 1. Just checking if a variable name appears on a line may not suffice (a "sloppy" user could assign multiple variables on one line), and variable settings can cover multiple lines (arrays), such that it can be harder to detect their comment which is completely at the end of the setting (i.e. after the first semi-colon that is not within a string or PHP comment). Losing the comment would be unfortunate but perhaps not extremely bad, since drupal_write_settings is normally only used during the installation of Drupal, so it's a one-time process.

Compare $GLOBALS before/after reading settings.php (bootstrap)
An alternative detection method would be to have bootstrap figure out which variables got added(/changed) while reading settings.php (e.g. by comparing $GLOBALS before and after or so). This too would make the comments go lost, though.

A combination of both the above methods might also work, i.e. try to find all variables and comments by reading settings.php, and just append any missed variables from the bootstrap information.

Rewrite from settings.php
Another option is to read settings.php instead of default.settings.php while rewriting the settings instead (with fallback to default.settings.php if settings.php is empty or non-existent). This way all manual changes to settings.php can be kept.

However, when replacing a variable that uses multiple lines for its value (arrays are typical examples, like $databases) it may be complicated to find exactly the lines the variable uses and thus which lines need to be replaced. Again, perhaps a user sets two variables on one line (separated by a semi-colon) so that option has to be detected as well.

Any comments? Any better ideas? Anyone know how to get the reading of existing settings done properly?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

haffmans’s picture

Adding issue tags

rickvug’s picture

@haffmans Is this still on your radar? Any code? If possible, a patch would definitely get more attention from core devs.

haffmans’s picture

I could still use it, but haven't had time to work on this yet. For now I'm working with prepared settings.php files which are read-only through the entire installation. Extra messages are in the installation profile demanding settings if need be, but require manual editing - so all the work I have so far is specific to installation profiles.

I'll leave it open for now, but have no time to solve it anytime soon.

David_Rothstein’s picture

Version: 7.x-dev » 8.x-dev

The patch at #852352: Make it possible to re-use the internal logic of drupal_rewrite_settings() in other installation processes might be a good start here, since it allows you to use files other than default.settings.php as the source from which settings.php is written.

David_Rothstein’s picture

Title: Allow installation profiles to write extra information to settings.php » Prevent drupal_rewrite_settings() from overwriting customizations made to settings.php
Status: Active » Needs review
FileSize
4.7 KB

Retitling, since this has use cases beyond install profiles (for example, someone who modifies settings.php by hand before installing should not have their modifications overwritten by the installer, as @alexpott has pointed out in the discussion at #1464944: Installation of configuration system fails in some cases).

Reading over this issue again, it actually seems to me like the last option in the original writeup ("Rewrite from settings.php") is the best way to go. The issue of multi-lined variables described there is the only problem, but if we rewrite drupal_rewrite_settings() to use modern PHP, we more or less get that functionality for free and probably fix some other limitations as well.

The attached patch does this. Notes:

  1. This adds the PHP tokenizer extension as a requirement for Drupal to be installed, but that's compiled into PHP by default so shouldn't be a problem in general. (Drupal 7 actually almost added this as a requirement for a different reason, although in the end did not.)
  2. To keep things simple, I've removed the ability for drupal_rewrite_settings() to write newly-defined constants into settings.php (just variables). We weren't using that anywhere, and the code seemed very problematic anyway (since it allowed for confusion between variable and constant names).
sun’s picture

This just bit me, as I prepared some changes in settings.php, forgot to git commit, and performed an installation. All work gone :(

Needless to amend, from my perspective this is a ridiculous bug.

Will restore my settings.php..., and then test this patch.

sun’s picture

Category: feature » task
Status: Needs review » Reviewed & tested by the community
FileSize
1.05 KB
4.71 KB

Excellent!

Only minimal/super-minor changes, so RTBC!

catch’s picture

Status: Reviewed & tested by the community » Fixed

This looks good to me, committed/pushed to 8.x.

Status: Fixed » Closed (fixed)
Issue tags: -installation, -settings.php, -installation profiles

Automatically closed -- issue fixed for 2 weeks with no activity.