Last updated November 5, 2012. Created by sun on July 2, 2012.
Edited by znerol, miro_dietiker, penyaskito, barraponto. Log in to edit this page.
In Drupal 7 and before one of the common ways of storing settings was using variable_get() and variable_set(). In Drupal 8 these have been replaced with the new configuration system API/storage.
Short introduction to CMI
- Modules store default settings in configuration files that are stored in a
config/folder in the module root directory. - When a module is enabled these default settings are copied to a 'config' folder inside sites/default/files. This folder has a unique suffix for security reasons (eg.
config_dWrEJUolcldeMHORCNbISC_GcGNM_cVAm7s9fVtru-E) - When settings are changed by a site administrator these are stored both in the database (in the
cache_configtable) and in the config files.
Upgrade procedure
- Decide on a config object name and a name for the settings. Simple settings can be stored in a config object named
<module_name>.settings, while for more complex settings it is advisable to use sub-keys. See the guidelines below. - Create a folder named
configin your module's root directory. - Create the default settings file and put the default configuration in. The filename convention is
<module_name>.<config_object_name>.<optional_sub_key>.yml. For example, this is the config file for the 'large' image style from the Image module (image.style.large.yml):name: large
label: Large (480x480)
effects:
ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d:
name: image_scale
data:
width: '480'
height: '480'
upscale: '1'
weight: '0'
ieid: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d - Grep the entire code base and replace all instances of
variable_get()andvariable_set()withconfig()->get()andconfig()->set(). An example:<?php
$items_per_page = config('node.settings')->get('items_per_page');
?><?php
function node_form_system_site_information_settings_form_submit($form, &$form_state) {
config('node.settings')
->set('items_per_page', $form_state['values']['default_nodes_main'])
->save();
}
?> - Create an update hook that updates the variables to CMI with update_variables_to_config(). Example:
<?php
/**
* Converts default_nodes_main variable to config.
*
* @ingroup config_upgrade
*/
function node_update_8009() {
update_variables_to_config('node.settings', array(
// 'old_variable' => 'new_config.sub_key'
'default_nodes_main' => 'items_per_page'
));
}
?>
Guidelines
- Within your conversion issue work, convert one variable at a time.
- Determine the variable name to convert.
- Grep the entire Drupal code base for the variable name and identify all instances that need to be updated.
- Speed up greps by checking
/corefirst. But do not forget to grep/profiles.
- New configuration objects are only picked up when a module is first enabled. If you add new configuration to a module that is already enabled, you should disable, uninstall and reenable the module for the configuration files to appear.
- Keep configuration object names short and concise.
-
If a module has only one set of settings (i.e., one settings form that will result in one configuration object), then the standard configuration object name is
$module.settings.The following bullets only apply to modules that need multiple configuration objects, in which case "settings" would be ambiguous:
- Given a module settings form
system_site_information_settings_form()that manages the variables:site_name
site_mail
site_frontpage
site_403
... - Understand that the primary namespace/owner of the configuration object is System module, so the configuration object name has to start with
system.. - Do not convert the form constructor function's name as-is for the configuration object name (
system.site-information). No Drupal developer wants to have to remember or deal with needlessly long names on a daily basis. - Instead, find the common denominator and shortest base name of all variables (
site) and choose an appropriate configuration object name:system.site
-
- Strip the configuration object name (or parts of it) from key names.
- Given a new configuration object name:
system.site
and a variable name:site_name - Understand that converting
site_nameintosystem.site:site_nameis bad DX. ;) - Instead, remove the duplicate
site_from the key name; i.e.:system.site:name
- Given a new configuration object name:
- Leverage sub-keys.
- Determine and understand the meaning of the entire set of variables to be converted.
- Given a subset of variables:
site_frontpage
site_403
site_404 - Research a bit to understand that all of them refer to internal router paths that denote pages to be shown in certain cases.
- Do not convert them to meaningless
frontpage,403,404. - Instead, leverage sub-keys and introduce DX sanity for D8 developers:
page.front
page.403
page.404
- Direct access, or provide context.
config('system.site')->get('name')is fine when being invoked only once within a function.- It's also fine, if the respective code is only reached through certain code conditions.
- However, when
config('system.site')is unconditionally used multiple times within a function, then only invoke it once. - Unless the context is crystal clear, try to avoid the ambiguous variable name
$config. - Instead, use a self-descriptive variable name; e.g.:
$site_config = config('system.site');
- Use system_config_form().
- For a simple settings form
somemodule_form(), write a form submission handler to save the configuration; e.g.,somemodule_form_submit(). - End the form with:
return system_config_form($form, $form_state);
This retains a consistent form actions container and submit button on settings forms. It also adds a handler for outputting a consistent (positive) confirmation message after form submission. However, it does NOT save any configuration like system_settings_form() did before.somemodule_form_submit()is responsible for that. - This takes effect until #1324618: Implement automated config saving for simple settings forms is resolved.
- For a simple settings form
Upgrade path tests
- Prefill your database:
core/modules/system/tests/upgrade/drupal-7.system.database.php<?php
..
// Add non-default system settings.
db_insert('variable')->fields(array(
'name',
'value',
))
..
->values(array(
'name' => 'node_rank_promote',
'value' => 'i:10;',
))
->values(array(
'name' => 'node_rank_custom_from_contrib',
'value' => 'i:5;',
))
..
->execute();
..
?> - Preload the database values and check for expected values, example:
core/modules/system/lib/Drupal/system/Tests/Upgrade/SystemUpgradePathTest.php<?php
class SystemUpgradePathTest extends UpgradePathTestBase {
..
public function setUp() {
$this->databaseDumpFiles = array(
drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz',
drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.system.database.php',
);
parent::setUp();
}
..
public function testVariableUpgrade() {
..
$expected_config['node.settings'] = array(
'search_rank.promote' => 10,
'search_rank.custom_from_contrib' => 5,
);
..
foreach ($expected_config as $file => $values) {
$config = config($file);
$this->verbose(print_r($config->get(), TRUE));
foreach ($values as $name => $value) {
$stored = $config->get($name);
$this->assertEqual($value, $stored, format_string('Expected value for %name found: %stored (previously: %value).', array('%stored' => $stored, '%name' => $name, '%value' => $value)));
}
}
?>