Skip to content
Snippets Groups Projects
Commit 0ce7fabf authored by Angie Byron's avatar Angie Byron
Browse files

Issue #1447686 by sun, beejeebus, Pol, heyrocker, David Strauss: Allow...

Issue #1447686 by sun, beejeebus, Pol, heyrocker, David Strauss: Allow importing and synchronizing configuration when files are updated.
parent 3642d7f5
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
......@@ -91,13 +91,13 @@ function config_sync_get_changes(StorageInterface $source_storage, StorageInterf
foreach (array_intersect($source_names, $target_names) as $name) {
$source_config_data = $source_storage->read($name);
$target_config_data = $target_storage->read($name);
if ($source_config_data != $target_config_data) {
if ($source_config_data !== $target_config_data) {
$config_changes['change'][] = $name;
}
}
// Do not trigger subsequent synchronization operations if there are no
// changes in either category.
// changes in any category.
if (empty($config_changes['create']) && empty($config_changes['change']) && empty($config_changes['delete'])) {
return FALSE;
}
......@@ -128,6 +128,48 @@ function config_sync_changes(array $config_changes, StorageInterface $source_sto
}
}
/**
* Imports configuration from FileStorage to DatabaseStorage.
*
* @return bool|null
* TRUE if configuration was imported successfully, FALSE in case of a
* synchronization error, or NULL if there are no changes to synchronize.
*/
function config_import() {
// Retrieve a list of differences between FileStorage and DatabaseStorage.
// @todo Leverage DI + config.storage.info.
$source_storage = new FileStorage();
$target_storage = new DatabaseStorage();
$config_changes = config_sync_get_changes($source_storage, $target_storage);
if (empty($config_changes)) {
return;
}
if (!lock_acquire(__FUNCTION__)) {
// Another request is synchronizing configuration.
// Return a negative result for UI purposes. We do not differentiate between
// an actual synchronization error and a failed lock, because concurrent
// synchronizations are an edge-case happening only when multiple developers
// or site builders attempt to do it without coordinating.
return FALSE;
}
$success = TRUE;
try {
$remaining_changes = config_import_invoke_owner($config_changes, $source_storage, $target_storage);
config_sync_changes($remaining_changes, $source_storage, $target_storage);
// Flush all caches and reset static variables after a successful import.
drupal_flush_all_caches();
}
catch (ConfigException $e) {
watchdog_exception('config_import', $e);
$success = FALSE;
}
lock_release(__FUNCTION__);
return $success;
}
/**
* Invokes MODULE_config_import() callbacks for configuration changes.
*
......@@ -176,3 +218,20 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou
}
return $config_changes;
}
/**
* Exports configuration from DatabaseStorage to FileStorage.
*/
function config_export() {
// Retrieve a list of differences between DatabaseStorage and FileStorage.
// @todo Leverage DI + config.storage.info.
$source_storage = new DatabaseStorage();
$target_storage = new FileStorage();
$config_changes = config_sync_get_changes($source_storage, $target_storage);
if (empty($config_changes)) {
return;
}
config_sync_changes($config_changes, $source_storage, $target_storage);
return TRUE;
}
<?php
/**
* @file
* Definition of Drupal\config\Tests\ConfigImportTest.
*/
namespace Drupal\config\Tests;
use Drupal\Core\Config\DatabaseStorage;
use Drupal\Core\Config\FileStorage;
use Drupal\simpletest\WebTestBase;
/**
* Tests importing configuration from files into active store.
*/
class ConfigImportTest extends WebTestBase {
public static function getInfo() {
return array(
'name' => 'Import configuration',
'description' => 'Tests importing configuration from files into active store.',
'group' => 'Configuration',
);
}
function setUp() {
parent::setUp(array('config_test'));
}
/**
* Tests deletion of configuration during import.
*/
function testDeleted() {
$name = 'config_test.system';
$dynamic_name = 'config_test.dynamic.default';
// Verify the default configuration values exist.
$config = config($name);
$this->assertIdentical($config->get('foo'), 'bar');
$config = config($dynamic_name);
$this->assertIdentical($config->get('id'), 'default');
// Export.
config_export();
// Delete the configuration objects.
$file_storage = new FileStorage();
$file_storage->delete($name);
$file_storage->delete($dynamic_name);
// Import.
config_import();
// Verify the values have disappeared.
$database_storage = new DatabaseStorage();
$this->assertIdentical($database_storage->read($name), FALSE);
$this->assertIdentical($database_storage->read($dynamic_name), FALSE);
$config = config($name);
$this->assertIdentical($config->get('foo'), NULL);
$config = config($dynamic_name);
$this->assertIdentical($config->get('id'), NULL);
}
/**
* Tests creation of configuration during import.
*/
function testNew() {
$name = 'config_test.new';
$dynamic_name = 'config_test.dynamic.new';
// Verify the configuration to create does not exist yet.
$file_storage = new FileStorage();
$this->assertIdentical($file_storage->exists($name), FALSE, $name . ' not found.');
$this->assertIdentical($file_storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.');
// Export.
config_export();
// Create new configuration objects.
$file_storage->write($name, array(
'add_me' => 'new value',
));
$file_storage->write($dynamic_name, array(
'id' => 'new',
'label' => 'New',
));
$this->assertIdentical($file_storage->exists($name), TRUE, $name . ' found.');
$this->assertIdentical($file_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
// Import.
config_import();
// Verify the values appeared.
$config = config($name);
$this->assertIdentical($config->get('add_me'), 'new value');
$config = config($dynamic_name);
$this->assertIdentical($config->get('label'), 'New');
}
/**
* Tests updating of configuration during import.
*/
function testUpdated() {
$name = 'config_test.system';
$dynamic_name = 'config_test.dynamic.default';
// Export.
config_export();
// Replace the file content of the existing configuration objects.
$file_storage = new FileStorage();
$this->assertIdentical($file_storage->exists($name), TRUE, $name . ' found.');
$this->assertIdentical($file_storage->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
$file_storage->write($name, array(
'foo' => 'beer',
));
$file_storage->write($dynamic_name, array(
'id' => 'default',
'label' => 'Updated',
));
// Verify the active store still returns the default values.
$config = config($name);
$this->assertIdentical($config->get('foo'), 'bar');
$config = config($dynamic_name);
$this->assertIdentical($config->get('label'), 'Default');
// Import.
config_import();
// Verify the values were updated.
$config = config($name);
$this->assertIdentical($config->get('foo'), 'beer');
$config = config($dynamic_name);
$this->assertIdentical($config->get('label'), 'Updated');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment