Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
13928d36
Commit
13928d36
authored
Mar 09, 2013
by
webchick
Browse files
Issue
#1921818
by chx: Modify drupal_rewrite_settings() to allow writing $settings values.
parent
279962e3
Changes
3
Hide whitespace changes
Inline
Side-by-side
core/includes/install.core.inc
View file @
13928d36
...
...
@@ -1102,11 +1102,11 @@ function install_settings_form_submit($form, &$form_state) {
global
$install_state
;
// Update global settings array and save.
$settings
[
'databases'
]
=
array
(
$settings
[
'databases'
]
=
(
object
)
array
(
'value'
=>
array
(
'default'
=>
array
(
'default'
=>
$form_state
[
'storage'
][
'database'
])),
'required'
=>
TRUE
,
);
$settings
[
'drupal_hash_salt'
]
=
array
(
$settings
[
'drupal_hash_salt'
]
=
(
object
)
array
(
'value'
=>
drupal_hash_base64
(
drupal_random_bytes
(
55
)),
'required'
=>
TRUE
,
);
...
...
core/includes/install.inc
View file @
13928d36
...
...
@@ -166,58 +166,144 @@ function drupal_get_database_types() {
/**
* 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.
*
* @param $settings
* An array of settings that need to be updated.
* 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.
* @code
* $settings['config_directories'] = array(
* CONFIG_ACTIVE_DIRECTORY => array(
* 'path' => (object) array(
* 'value' => 'config__hash/active'
* 'required' => TRUE,
* ),
* ),
* CONFIG_STAGING_DIRECTORY => array(
* 'path' => (object) array(
* 'value' => 'config_hash/staging',
* 'required' => TRUE,
* ),
* ),
* );
* @endcode
* gets dumped as:
* @code
* $config_directories['active']['path'] = 'config__hash/active';
* $config_directories['staging']['path'] = 'config__hash/staging'
* @endcode
*/
function
drupal_rewrite_settings
(
$settings
=
array
())
{
drupal_static_reset
(
'conf_path'
);
$settings_file
=
conf_path
(
FALSE
)
.
'/settings.php'
;
function
drupal_rewrite_settings
(
$settings
=
array
()
,
$settings_file
=
NULL
)
{
if
(
!
isset
(
$settings_file
))
{
$settings_file
=
conf_path
(
FALSE
)
.
'/settings.php'
;
}
// Build list of setting names and insert the values into the global namespace.
$
key
s
=
array
();
$
variable_name
s
=
array
();
foreach
(
$settings
as
$setting
=>
$data
)
{
$GLOBALS
[
$setting
]
=
$data
[
'value'
]
;
$
keys
[
]
=
$setting
;
_drupal_rewrite_settings_global
(
$GLOBALS
[
$setting
]
,
$data
)
;
$
variable_names
[
'$'
.
$setting
]
=
$setting
;
}
$buffer
=
NULL
;
$contents
=
file_get_contents
(
DRUPAL_ROOT
.
'/'
.
$settings_file
);
if
(
$contents
!==
FALSE
)
{
// Step through each token in settings.php and replace any variables that
// are in the passed-in array.
$replacing_variable
=
FALSE
;
$buffer
=
''
;
$state
=
'default'
;
foreach
(
token_get_all
(
$contents
)
as
$token
)
{
// Strip off the leading "$" before comparing the variable name.
if
(
is_array
(
$token
)
&&
$token
[
0
]
==
T_VARIABLE
&&
(
$variable_name
=
substr
(
$token
[
1
],
1
))
&&
in_array
(
$variable_name
,
$keys
))
{
// Write the new value to settings.php in the following format:
// $[setting] = '[value]'; // [comment]
$setting
=
$settings
[
$variable_name
];
$buffer
.
=
'$'
.
$variable_name
.
' = '
.
var_export
(
$setting
[
'value'
],
TRUE
)
.
';'
;
if
(
!
empty
(
$setting
[
'comment'
]))
{
$buffer
.
=
' // '
.
$setting
[
'comment'
];
}
unset
(
$settings
[
$variable_name
]);
$replacing_variable
=
TRUE
;
if
(
is_array
(
$token
))
{
list
(
$type
,
$value
)
=
$token
;
}
else
{
// Write a regular token (that is not part of a variable we're
// replacing) to settings.php directly.
if
(
!
$replacing_variable
)
{
$buffer
.
=
is_array
(
$token
)
?
$token
[
1
]
:
$token
;
}
// When we hit a semicolon, we are done with the code that defines the
// variable that is being replaced.
if
(
$token
==
';'
)
{
$replacing_variable
=
FALSE
;
$type
=
-
1
;
$value
=
$token
;
}
// Do not operate on whitespace.
if
(
!
in_array
(
$type
,
array
(
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
(
'Unepxected token after replacing value.'
);
}
break
;
}
}
$buffer
.
=
$value
;
}
// Add required settings that were missing from settings.php.
foreach
(
$settings
as
$setting
=>
$data
)
{
if
(
!
empty
(
$data
[
'required'
]))
{
$buffer
.
=
"
\$
$setting
= "
.
var_export
(
$data
[
'value'
],
TRUE
)
.
";
\n
"
;
}
foreach
(
$settings
as
$name
=>
$setting
)
{
$buffer
.
=
_drupal_rewrite_settings_dump
(
$setting
,
'$'
.
$name
);
}
// Write the new settings file.
...
...
@@ -230,6 +316,123 @@ function drupal_rewrite_settings($settings = array()) {
}
}
/**
* Helper for drupal_rewrite_settings().
*
* Checks whether this token represents a scalar or NULL.
*
* @param int $type
* The token type
* @see token_name().
* @param string $value
* The value of the token.
*
* @return bool
* TRUE if this token represents a scalar or NULL.
*/
function
_drupal_rewrite_settings_is_simple
(
$type
,
$value
)
{
$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
),
array
(
'TRUE'
,
'FALSE'
,
'NULL'
));
return
$is_integer
||
$is_float
||
$is_string
||
$is_boolean_or_null
;
}
/**
* Helper for drupal_rewrite_settings().
*
* Checks whether this token represents a valid array index: a number or a
* stirng.
*
* @param int $type
* The token type
* @see token_name().
*
* @return bool
* TRUE if this token represents a number or a string.
*/
function
_drupal_rewrite_settings_is_array_index
(
$type
)
{
$is_integer
=
$type
==
T_LNUMBER
;
$is_float
=
$type
==
T_DNUMBER
;
$is_string
=
$type
==
T_CONSTANT_ENCAPSED_STRING
;
return
$is_integer
||
$is_float
||
$is_string
;
}
/**
* Helper for drupal_rewrite_settings().
*
* Makes the new settings global.
*
* @param array|NULL $ref
* A reference to a nested index in $GLOBALS.
* @param array|object $variable
* The nested value of the setting being copied.
*/
function
_drupal_rewrite_settings_global
(
&
$ref
,
$variable
)
{
if
(
is_object
(
$variable
))
{
$ref
=
$variable
->
value
;
}
else
{
foreach
(
$variable
as
$k
=>
$v
)
{
_drupal_rewrite_settings_global
(
$ref
[
$k
],
$v
);
}
}
}
/**
* Helper for drupal_rewrite_settings().
*
* Dump the relevant value properties.
*
* @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.
*/
function
_drupal_rewrite_settings_dump
(
$variable
,
$variable_name
)
{
$return
=
''
;
if
(
is_object
(
$variable
))
{
if
(
!
empty
(
$variable
->
required
))
{
$return
.
=
_drupal_rewrite_settings_dump_one
(
$variable
,
"
$variable_name
= "
,
"
\n
"
);
}
}
else
{
foreach
(
$variable
as
$k
=>
$v
)
{
$return
.
=
_drupal_rewrite_settings_dump
(
$v
,
$variable_name
.
"['"
.
$k
.
"']"
);
}
}
return
$return
;
}
/**
* Helper for drupal_rewrite_settings().
*
* Dump the value of a value property and adds the comment if it exists.
*
* @param stdClass $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.
*/
function
_drupal_rewrite_settings_dump_one
(
\
stdClass
$variable
,
$prefix
=
''
,
$suffix
=
''
)
{
$return
=
$prefix
.
var_export
(
$variable
->
value
,
TRUE
)
.
';'
;
if
(
!
empty
(
$variable
->
comment
))
{
$return
.
=
' // '
.
$variable
->
comment
;
}
$return
.
=
$suffix
;
return
$return
;
}
/**
* Creates the config directory and ensures it is operational.
*
...
...
@@ -244,15 +447,18 @@ function drupal_install_config_directories() {
if
(
empty
(
$config_directories
))
{
$config_directories_hash
=
drupal_hash_base64
(
drupal_random_bytes
(
55
));
$settings
[
'config_directories'
]
=
array
(
'value'
=>
array
(
CONFIG_ACTIVE_DIRECTORY
=>
array
(
'path'
=>
'config_'
.
$config_directories_hash
.
'/active'
,
CONFIG_ACTIVE_DIRECTORY
=>
array
(
'path'
=>
(
object
)
array
(
'value'
=>
'config_'
.
$config_directories_hash
.
'/active'
,
'required'
=>
TRUE
,
),
CONFIG_STAGING_DIRECTORY
=>
array
(
'path'
=>
'config_'
.
$config_directories_hash
.
'/staging'
,
),
CONFIG_STAGING_DIRECTORY
=>
array
(
'path'
=>
(
object
)
array
(
'value'
=>
'config_'
.
$config_directories_hash
.
'/staging'
,
'required'
=>
TRUE
,
),
),
'required'
=>
TRUE
,
);
// Rewrite settings.php, which also sets the value as global variable.
drupal_rewrite_settings
(
$settings
);
...
...
core/modules/system/lib/Drupal/system/Tests/System/SettingsRewriteTest.php
0 → 100644
View file @
13928d36
<?php
/**
* @file
* Contains Drupal\system\Tests\System\SettingsRewriteTest.
*/
namespace
Drupal\system\Tests\System
;
use
Drupal\simpletest\UnitTestBase
;
/**
* Tests the drupal_rewrite_settings() function.
*/
class
SettingsRewriteTest
extends
UnitTestBase
{
public
static
function
getInfo
()
{
return
array
(
'name'
=>
'drupal_rewrite_settings()'
,
'description'
=>
'Tests the drupal_rewrite_settings() function.'
,
'group'
=>
'System'
,
);
}
/**
* Tests the drupal_rewrite_settings() function.
*/
function
testDrupalRewriteSettings
()
{
include_once
DRUPAL_ROOT
.
'/core/includes/install.inc'
;
$tests
=
array
(
array
(
'original'
=>
'$no_index_value_scalar = TRUE;'
,
'settings'
=>
array
(
'no_index_value_scalar'
=>
(
object
)
array
(
'value'
=>
FALSE
,
'comment'
=>
'comment'
,
),
),
'expected'
=>
'$no_index_value_scalar = false; // comment'
,
),
array
(
'original'
=>
'$no_index_value_scalar = TRUE;'
,
'settings'
=>
array
(
'no_index_value_foo'
=>
array
(
'foo'
=>
array
(
'value'
=>
(
object
)
array
(
'value'
=>
NULL
,
'required'
=>
TRUE
,
'comment'
=>
'comment'
,
),
),
),
),
'expected'
=>
<<<'EXPECTED'
$no_index_value_scalar = TRUE;
$no_index_value_foo['foo']['value'] = NULL; // comment
EXPECTED
),
array
(
'original'
=>
'$no_index_value_array = array("old" => "value");'
,
'settings'
=>
array
(
'no_index_value_array'
=>
(
object
)
array
(
'value'
=>
FALSE
,
'required'
=>
TRUE
,
'comment'
=>
'comment'
,
),
),
'expected'
=>
'$no_index_value_array = array("old" => "value");
$no_index_value_array = false; // comment'
,
),
array
(
'original'
=>
'$has_index_value_scalar["foo"]["bar"] = NULL;'
,
'settings'
=>
array
(
'has_index_value_scalar'
=>
array
(
'foo'
=>
array
(
'bar'
=>
(
object
)
array
(
'value'
=>
FALSE
,
'required'
=>
TRUE
,
'comment'
=>
'comment'
,
),
),
),
),
'expected'
=>
'$has_index_value_scalar["foo"]["bar"] = false; // comment'
,
),
array
(
'original'
=>
'$has_index_value_scalar["foo"]["bar"] = "foo";'
,
'settings'
=>
array
(
'has_index_value_scalar'
=>
array
(
'foo'
=>
array
(
'value'
=>
(
object
)
array
(
'value'
=>
array
(
'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
=
variable_get
(
'file_public_path'
,
conf_path
()
.
'/files'
)
.
'/mock_settings.php'
;
file_put_contents
(
DRUPAL_ROOT
.
'/'
.
$filename
,
"<?php
\n
"
.
$test
[
'original'
]
.
"
\n
"
);
drupal_rewrite_settings
(
$test
[
'settings'
],
$filename
);
$this
->
assertEqual
(
file_get_contents
(
DRUPAL_ROOT
.
'/'
.
$filename
),
"<?php
\n
"
.
$test
[
'expected'
]
.
"
\n
"
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment