Skip to content
Snippets Groups Projects
Commit ffaabb7c authored by catch's avatar catch
Browse files

Issue #1998576 by beejeebus, alexpott, swentel: Make the config import process...

Issue #1998576 by beejeebus, alexpott, swentel: Make the config import process use full config trees again.
parent d790fb7a
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
Showing
with 180 additions and 346 deletions
...@@ -22,12 +22,6 @@ ...@@ -22,12 +22,6 @@
* The name of the module or theme to install default configuration for. * The name of the module or theme to install default configuration for.
*/ */
function config_install_default_config($type, $name) { function config_install_default_config($type, $name) {
// If this module defines any ConfigEntity types then create an empty
// manifest file for each of them.
foreach (config_get_module_config_entities($name) as $entity_info) {
config('manifest.' . $entity_info['config_prefix'])->save();
}
$config_dir = drupal_get_path($type, $name) . '/config'; $config_dir = drupal_get_path($type, $name) . '/config';
if (is_dir($config_dir)) { if (is_dir($config_dir)) {
$source_storage = new FileStorage($config_dir); $source_storage = new FileStorage($config_dir);
...@@ -60,12 +54,6 @@ function config_uninstall_default_config($type, $name) { ...@@ -60,12 +54,6 @@ function config_uninstall_default_config($type, $name) {
foreach ($config_names as $config_name) { foreach ($config_names as $config_name) {
config($config_name)->delete(); config($config_name)->delete();
} }
// If this module defines any ConfigEntity types, then delete the manifest
// file for each of them.
foreach (config_get_module_config_entities($name) as $entity_type) {
config('manifest.' . $entity_info['config_prefix'])->delete();
}
} }
/** /**
......
...@@ -1410,29 +1410,6 @@ function update_variables_to_config($config_name, array $variable_map) { ...@@ -1410,29 +1410,6 @@ function update_variables_to_config($config_name, array $variable_map) {
db_delete('variable')->condition('name', array_keys($variable_map), 'IN')->execute(); db_delete('variable')->condition('name', array_keys($variable_map), 'IN')->execute();
} }
/**
* Adds entries in a configuration entity manifest file during updates.
*
* @param string $config_prefix
* The configuration entity prefix from the annotation.
* @param array $ids
* An array of configuration entities to add to the manifest.
*/
function update_config_manifest_add($config_prefix, array $ids) {
$manifest = config('manifest.' . $config_prefix);
// Add record to manifest for each config entity. Operate on the data array
// as a whole, because $manifest->get() would treat dots in ids as nesting.
$data = $manifest->get();
foreach ($ids as $id) {
$data[$id] = array('name' => $config_prefix . '.' . $id);
}
$manifest->setData($data);
// Write manifest to disk.
$manifest->save();
}
/** /**
* Installs a default configuration file into the active store. * Installs a default configuration file into the active store.
* *
......
...@@ -373,15 +373,6 @@ public function delete(array $entities) { ...@@ -373,15 +373,6 @@ public function delete(array $entities) {
foreach ($entities as $id => $entity) { foreach ($entities as $id => $entity) {
$config = $this->configFactory->get($this->getConfigPrefix() . $entity->id()); $config = $this->configFactory->get($this->getConfigPrefix() . $entity->id());
$config->delete(); $config->delete();
// Remove the entity from the manifest file. Entity IDs can contain a dot
// so we can not use Config::clear() to remove the entity from the
// manifest.
$manifest = $this->configFactory->get('manifest.' . $this->entityInfo['config_prefix']);
$manifest_data = $manifest->get();
unset($manifest_data[$entity->id()]);
$manifest->setData($manifest_data);
$manifest->save();
} }
$this->postDelete($entities); $this->postDelete($entities);
...@@ -452,28 +443,6 @@ public function save(EntityInterface $entity) { ...@@ -452,28 +443,6 @@ public function save(EntityInterface $entity) {
$this->invokeHook('insert', $entity); $this->invokeHook('insert', $entity);
} }
$update_manifest = FALSE;
$config = $this->configFactory->get('manifest.' . $this->entityInfo['config_prefix']);
$manifest = $config->get();
// If the save operation resulted in a rename remove the old entity id from
// the manifest file.
if ($id !== $entity->id()) {
// Entity IDs can contain a dot so we can not use Config::clear() to
// remove the entity from the manifest.
unset($manifest[$id]);
$update_manifest = TRUE;
}
// Add this entity to the manifest file if necessary.
if (!isset($manifest[$entity->id()])) {
$manifest[$entity->id()] = array(
'name' => $this->getConfigPrefix() . $entity->id(),
);
$update_manifest = TRUE;
}
if ($update_manifest) {
$config->setData($manifest)->save();
}
unset($entity->original); unset($entity->original);
return $return; return $return;
......
...@@ -139,13 +139,10 @@ public function addChangelistCreate() { ...@@ -139,13 +139,10 @@ public function addChangelistCreate() {
*/ */
public function addChangelistUpdate() { public function addChangelistUpdate() {
foreach (array_intersect($this->getSourceNames(), $this->getTargetNames()) as $name) { foreach (array_intersect($this->getSourceNames(), $this->getTargetNames()) as $name) {
// Ignore manifest files. $source_config_data = $this->sourceStorage->read($name);
if (substr($name, 0, 9) != 'manifest.') { $target_config_data = $this->targetStorage->read($name);
$source_config_data = $this->sourceStorage->read($name); if ($source_config_data !== $target_config_data) {
$target_config_data = $this->targetStorage->read($name); $this->addChangeList('update', array($name));
if ($source_config_data !== $target_config_data) {
$this->addChangeList('update', array($name));
}
} }
} }
return $this; return $this;
......
<?php
/**
* @file
* Contains \Drupal\Core\Config\StorageComparerManifest.
*/
namespace Drupal\Core\Config;
/**
* Defines a config storage comparer that uses config entity manifests.
*
* Config entities maintain 'manifest' files that list the objects they are
* currently handling. Each file is a simple indexed array of config object
* names. In order to generate a list of objects that have been created or
* deleted we need to open these files in both the source and target storage,
* generate an array of the objects, and compare them.
*/
class StorageComparerManifest extends StorageComparer {
/**
* List of config entities managed by manifests in the source storage.
*
* @see \Drupal\Core\Config\StorageComparerManifest::getSourceManifestData()
*
* @var array
*/
protected $sourceManifestData = array();
/**
* List of config entities managed by manifests in the target storage.
*
* @see \Drupal\Core\Config\StorageComparerManifest::getTargetManifestData()
*
* @var array
*/
protected $targetManifestData = array();
/**
* {@inheritdoc}
*/
public function addChangelistDelete() {
foreach (array_diff_key($this->getTargetManifestData(), $this->getSourceManifestData()) as $value) {
$this->addChangeList('delete', array($value['name']));
}
return $this;
}
/**
* {@inheritdoc}
*/
public function addChangelistCreate() {
foreach (array_diff_key($this->getSourceManifestData(), $this->getTargetManifestData()) as $value) {
$this->addChangeList('create', array($value['name']));
}
return $this;
}
/**
* Gets the list of config entities from the source storage's manifest files.
*
* @return array
* The list of config entities in the source storage whose entity type has a
* manifest in the source storage.
*/
protected function getSourceManifestData() {
if (empty($this->sourceManifestData)) {
foreach ($this->getSourceStorage()->listAll('manifest') as $name) {
if ($source_manifest_data = $this->getSourceStorage()->read($name)) {
$this->sourceManifestData = array_merge($this->sourceManifestData, $source_manifest_data);
}
}
}
return $this->sourceManifestData;
}
/**
* Gets the list of config entities from the target storage's manifest files.
*
* @see \Drupal\Core\Config\ConfigImporter::getSourceManifestData()
*
* @return array
* The list of config entities in the target storage whose entity type has a
* manifest in the source storage.
*/
protected function getTargetManifestData() {
if (empty($this->targetManifestData)) {
foreach ($this->getSourceStorage()->listAll('manifest') as $name) {
if ($target_manifest_data = $this->targetStorage->read($name)) {
$this->targetManifestData = array_merge($this->targetManifestData, $target_manifest_data);
}
}
}
return $this->targetManifestData;
}
/**
* {@inheritdoc}
*/
public function reset() {
$this->sourceManifestData = $this->targetManifestData = array();
return parent::reset();
}
}
...@@ -271,7 +271,6 @@ function block_update_8008() { ...@@ -271,7 +271,6 @@ function block_update_8008() {
'type' => 'text_textarea_with_summary', 'type' => 'text_textarea_with_summary',
)) ))
->save(); ->save();
update_config_manifest_add('entity.form_display', array($form_display->get('id')));
// Initialize state for future calls. // Initialize state for future calls.
$sandbox['last'] = 0; $sandbox['last'] = 0;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
use Drupal\Core\Ajax\OpenModalDialogCommand; use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Config\ConfigException; use Drupal\Core\Config\ConfigException;
use Drupal\Core\Config\ConfigImporter; use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Config\StorageComparerManifest; use Drupal\Core\Config\StorageComparer;
use Drupal\Core\Config\StorageInterface; use Drupal\Core\Config\StorageInterface;
/** /**
...@@ -27,16 +27,8 @@ ...@@ -27,16 +27,8 @@
*/ */
function config_admin_sync_form(array &$form, array &$form_state, StorageInterface $source_storage) { function config_admin_sync_form(array &$form, array &$form_state, StorageInterface $source_storage) {
$source_list = $source_storage->listAll(); $source_list = $source_storage->listAll();
if (empty($source_list)) { $config_comparer = new StorageComparer(Drupal::service('config.storage.staging'), Drupal::service('config.storage'));
$form['no_changes'] = array( if (empty($source_list) || !$config_comparer->createChangelist()->hasChanges()) {
'#markup' => t('There is no configuration to import.'),
);
$form['actions']['#access'] = FALSE;
return $form;
}
$config_comparer = new StorageComparerManifest(Drupal::service('config.storage.staging'), Drupal::service('config.storage'));
if (!$config_comparer->createChangelist()->hasChanges()) {
$form['no_changes'] = array( $form['no_changes'] = array(
'#markup' => t('There are no configuration changes.'), '#markup' => t('There are no configuration changes.'),
); );
...@@ -146,14 +138,6 @@ function config_admin_import_form_submit($form, &$form_state) { ...@@ -146,14 +138,6 @@ function config_admin_import_form_submit($form, &$form_state) {
$config_importer->import(); $config_importer->import();
drupal_flush_all_caches(); drupal_flush_all_caches();
drupal_set_message(t('The configuration was imported successfully.')); drupal_set_message(t('The configuration was imported successfully.'));
// Once a sync completes, we empty the staging directory. This prevents
// changes from being accidentally overwritten by stray files getting
// imported later.
$source_storage = $config_importer->getStorageComparer()->getSourceStorage();
foreach ($source_storage->listAll() as $name) {
$source_storage->delete($name);
}
} }
catch (ConfigException $e) { catch (ConfigException $e) {
// Return a negative result for UI purposes. We do not differentiate between // Return a negative result for UI purposes. We do not differentiate between
......
...@@ -36,6 +36,19 @@ function config_permission() { ...@@ -36,6 +36,19 @@ function config_permission() {
return $permissions; return $permissions;
} }
/**
* Implements hook_file_download().
*/
function config_file_download($uri) {
$scheme = file_uri_scheme($uri);
$target = file_uri_target($uri);
if ($scheme == 'temporary' && $target == 'config.tar.gz') {
return array(
'Content-disposition' => 'attachment; filename="config.tar.gz"',
);
}
}
/** /**
* Implements hook_menu(). * Implements hook_menu().
*/ */
...@@ -48,6 +61,16 @@ function config_menu() { ...@@ -48,6 +61,16 @@ function config_menu() {
'access arguments' => array('synchronize configuration'), 'access arguments' => array('synchronize configuration'),
'file' => 'config.admin.inc', 'file' => 'config.admin.inc',
); );
$items['admin/config/development/export'] = array(
'title' => 'Configuration export',
'description' => 'Export your site configuration',
'route_name' => 'config_export',
);
$items['admin/config/development/import'] = array(
'title' => 'Configuration import',
'description' => 'Import configuration for your site',
'route_name' => 'config_import',
);
$items['admin/config/development/sync/diff/%'] = array( $items['admin/config/development/sync/diff/%'] = array(
'title' => 'Configuration file diff', 'title' => 'Configuration file diff',
'description' => 'Diff between active and staged configuraiton.', 'description' => 'Diff between active and staged configuraiton.',
......
...@@ -4,3 +4,21 @@ config_diff: ...@@ -4,3 +4,21 @@ config_diff:
_content: '\Drupal\config\Controller\ConfigController::diff' _content: '\Drupal\config\Controller\ConfigController::diff'
requirements: requirements:
_permission: 'synchronize configuration' _permission: 'synchronize configuration'
config_export_download:
pattern: '/admin/config/development/export-download'
defaults:
_controller: '\Drupal\config\Controller\ConfigController::downloadExport'
requirements:
_permission: 'export configuration'
config_export:
pattern: '/admin/config/development/export'
defaults:
_form: '\Drupal\config\Form\ConfigExportForm'
requirements:
_permission: 'export configuration'
config_import:
pattern: '/admin/config/development/import'
defaults:
_form: '\Drupal\config\Form\ConfigImportForm'
requirements:
_permission: 'import configuration'
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
use Drupal\Core\ControllerInterface; use Drupal\Core\ControllerInterface;
use Drupal\Core\Config\StorageInterface; use Drupal\Core\Config\StorageInterface;
use Drupal\Component\Archiver\ArchiveTar;
use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand; use Drupal\Core\Ajax\OpenModalDialogCommand;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -52,6 +53,20 @@ public function __construct(StorageInterface $target_storage, StorageInterface $ ...@@ -52,6 +53,20 @@ public function __construct(StorageInterface $target_storage, StorageInterface $
$this->sourceStorage = $source_storage; $this->sourceStorage = $source_storage;
} }
/**
* Downloads a tarball of the site configuration.
*/
public function downloadExport() {
$archiver = new ArchiveTar(file_directory_temp() . '/config.tar.gz', 'gz');
$config_dir = config_get_config_directory();
$config_files = array();
foreach (\Drupal::service('config.storage')->listAll() as $config_name) {
$config_files[] = $config_dir . '/' . $config_name . '.yml';
}
$archiver->createModify($config_files, '', config_get_config_directory());
return file_download('temporary', 'config.tar.gz');
}
/** /**
* Shows diff of specificed configuration file. * Shows diff of specificed configuration file.
* *
......
<?php
namespace Drupal\config\Form;
use Drupal\Core\Form\FormInterface;
class ConfigExportForm implements FormInterface {
public function getFormID() {
return 'config_export_form';
}
public function buildForm(array $form, array &$form_state) {
$form['#action'] = '/admin/config/development/export-download';
$form['description'] = array(
'#markup' => '<p>' . t('Use the export button below to download your site configuration.') . '</p>',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Export'),
);
return $form;
}
public function validateForm(array &$form, array &$form_state) {
}
public function submitForm(array &$form, array &$form_state) {
}
}
<?php
namespace Drupal\config\Form;
use Drupal\Core\Form\FormInterface;
use Drupal\Component\Archiver\ArchiveTar;
class ConfigImportForm implements FormInterface {
public function getFormID() {
return 'config_import_form';
}
public function buildForm(array $form, array &$form_state) {
$form['description'] = array(
'#markup' => '<p>' . t('Use the upload button below.') . '</p>',
);
$form['import_tarball'] = array(
'#type' => 'file',
'#value' => t('Select your configuration export file'),
'#description' => t('This form will redirect you to the import configuration screen.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Upload'),
);
return $form;
}
public function validateForm(array &$form, array &$form_state) {
if (!empty($_FILES['files']['error']['import_tarball'])) {
form_set_error('import_tarball', t('The import tarball could not be uploaded.'));
}
else {
$form_state['values']['import_tarball'] = $_FILES['files']['tmp_name']['import_tarball'];
}
}
public function submitForm(array &$form, array &$form_state) {
if ($path = $form_state['values']['import_tarball']) {
\Drupal::service('config.storage.staging')->deleteAll();
$archiver = new ArchiveTar($path, 'gz');
$files = array();
foreach ($archiver->listContent() as $file) {
$files[] = $file['filename'];
}
$archiver->extractList($files, config_get_config_directory(CONFIG_STAGING_DIRECTORY));
drupal_unlink($path);
drupal_set_message('Your configuration files were successfully uploaded, ready for import.');
$form_state['redirect'] = 'admin/config/development/sync';
}
}
}
...@@ -193,23 +193,6 @@ function testNameValidation() { ...@@ -193,23 +193,6 @@ function testNameValidation() {
catch (ConfigNameException $e) { catch (ConfigNameException $e) {
$this->pass($message); $this->pass($message);
} }
// Write configuration with an invalid name (missing a namespace) to
// staging.
$staging = $this->container->get('config.storage.staging');
$manifest_data = config('manifest.invalid_object_name')->get();
$manifest_data['new']['name'] = 'invalid';
$staging->write('manifest.invalid_object_name', $manifest_data);
// Verify that an exception is thrown when importing.
$message = 'Expected ConfigNameException was thrown when attempting to sync invalid configuration.';
try {
$this->configImporter()->import();
$this->fail($message);
}
catch (ConfigNameException $e) {
$this->pass($message);
}
} }
} }
...@@ -35,7 +35,6 @@ public static function getInfo() { ...@@ -35,7 +35,6 @@ public static function getInfo() {
* Tests CRUD operations. * Tests CRUD operations.
*/ */
function testCRUD() { function testCRUD() {
$manifest_name = 'manifest.config_test.dynamic';
$default_langcode = language_default()->langcode; $default_langcode = language_default()->langcode;
// Verify default properties on a newly created empty entity. // Verify default properties on a newly created empty entity.
$empty = entity_create('config_test', array()); $empty = entity_create('config_test', array());
...@@ -123,10 +122,6 @@ function testCRUD() { ...@@ -123,10 +122,6 @@ function testCRUD() {
$this->fail('EntityMalformedException was not thrown.'); $this->fail('EntityMalformedException was not thrown.');
} }
// Verify that the config manifest entry exists.
$manifest_data = config($manifest_name)->get();
$this->assertTrue(isset($manifest_data[$config_test->id()]), 'Configuration manifest for config_test.dynamic entities updated after an entity save.');
// Verify that the correct status is returned and properties did not change. // Verify that the correct status is returned and properties did not change.
$this->assertIdentical($status, SAVED_NEW); $this->assertIdentical($status, SAVED_NEW);
$this->assertIdentical($config_test->id(), $expected['id']); $this->assertIdentical($config_test->id(), $expected['id']);
...@@ -181,13 +176,6 @@ function testCRUD() { ...@@ -181,13 +176,6 @@ function testCRUD() {
// Verify that originalID points to new ID directly after renaming. // Verify that originalID points to new ID directly after renaming.
$this->assertIdentical($config_test->id(), $new_id); $this->assertIdentical($config_test->id(), $new_id);
$this->assertIdentical($config_test->getOriginalID(), $new_id); $this->assertIdentical($config_test->getOriginalID(), $new_id);
// Verify that the config manifest entry exists.
$manifest_data = config($manifest_name)->get();
// Check that the old id is not in the manifest.
$this->assertFalse(isset($manifest_data[$old_id]), 'Old id removed from configuration manifest after an entity save.');
// Check that the new id is in the manifest.
$this->assertTrue(isset($manifest_data[$new_id]), 'New id added to configuration manifest after an entity save.');
} }
// Test config entity prepopulation. // Test config entity prepopulation.
......
...@@ -29,6 +29,7 @@ function setUp() { ...@@ -29,6 +29,7 @@ function setUp() {
$this->web_user = $this->drupalCreateUser(array('synchronize configuration')); $this->web_user = $this->drupalCreateUser(array('synchronize configuration'));
$this->drupalLogin($this->web_user); $this->drupalLogin($this->web_user);
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
} }
/** /**
...@@ -40,13 +41,8 @@ function testImport() { ...@@ -40,13 +41,8 @@ function testImport() {
$storage = $this->container->get('config.storage'); $storage = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging'); $staging = $this->container->get('config.storage.staging');
// Verify the configuration to create and update does not exist yet.
$this->assertIdentical($staging->exists($name), FALSE, $name . ' not found.');
$this->assertIdentical($staging->exists($dynamic_name), FALSE, $dynamic_name . ' not found.');
// Verify that the import UI recognises that the staging folder is empty.
$this->drupalGet('admin/config/development/sync'); $this->drupalGet('admin/config/development/sync');
$this->assertText('There is no configuration to import.'); $this->assertText('There are no configuration changes.');
$this->assertNoFieldById('edit-submit', t('Import all')); $this->assertNoFieldById('edit-submit', t('Import all'));
// Create updated configuration object. // Create updated configuration object.
...@@ -66,15 +62,9 @@ function testImport() { ...@@ -66,15 +62,9 @@ function testImport() {
'protected_property' => '', 'protected_property' => '',
); );
$staging->write($dynamic_name, $original_dynamic_data); $staging->write($dynamic_name, $original_dynamic_data);
// Create manifest for new config entity.
$manifest_data = config('manifest.config_test.dynamic')->get();
$manifest_data[$original_dynamic_data['id']]['name'] = 'config_test.dynamic.' . $original_dynamic_data['id'];
$staging->write('manifest.config_test.dynamic', $manifest_data);
$this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); $this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
// Verify that both appear as new. // Verify that both appear as ready to import.
$this->drupalGet('admin/config/development/sync'); $this->drupalGet('admin/config/development/sync');
$this->assertText($name); $this->assertText($name);
$this->assertText($dynamic_name); $this->assertText($dynamic_name);
...@@ -82,13 +72,12 @@ function testImport() { ...@@ -82,13 +72,12 @@ function testImport() {
// Import and verify that both do not appear anymore. // Import and verify that both do not appear anymore.
$this->drupalPost(NULL, array(), t('Import all')); $this->drupalPost(NULL, array(), t('Import all'));
$this->assertUrl('admin/config/development/sync');
$this->assertNoText($name); $this->assertNoText($name);
$this->assertNoText($dynamic_name); $this->assertNoText($dynamic_name);
$this->assertNoFieldById('edit-submit', t('Import all')); $this->assertNoFieldById('edit-submit', t('Import all'));
// Verify that there are no further changes to import. // Verify that there are no further changes to import.
$this->assertText(t('There is no configuration to import.')); $this->assertText(t('There are no configuration changes.'));
// Verify site name has changed. // Verify site name has changed.
$this->assertIdentical($new_site_name, config('system.site')->get('name')); $this->assertIdentical($new_site_name, config('system.site')->get('name'));
...@@ -118,7 +107,6 @@ function testImportLock() { ...@@ -118,7 +107,6 @@ function testImportLock() {
// Attempt to import configuration and verify that an error message appears. // Attempt to import configuration and verify that an error message appears.
$this->drupalPost(NULL, array(), t('Import all')); $this->drupalPost(NULL, array(), t('Import all'));
$this->assertUrl('admin/config/development/sync');
$this->assertText(t('Another request may be synchronizing configuration already.')); $this->assertText(t('Another request may be synchronizing configuration already.'));
// Release the lock, just to keep testing sane. // Release the lock, just to keep testing sane.
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
namespace Drupal\config\Tests; namespace Drupal\config\Tests;
use Drupal\Core\Config\ConfigImporter; use Drupal\Core\Config\ConfigImporter;
use Drupal\Core\Config\StorageComparerManifest; use Drupal\Core\Config\ConfigImporterException;
use Drupal\Core\Config\StorageComparer;
use Drupal\simpletest\DrupalUnitTestBase; use Drupal\simpletest\DrupalUnitTestBase;
/** /**
...@@ -50,9 +51,10 @@ function setUp() { ...@@ -50,9 +51,10 @@ function setUp() {
unset($GLOBALS['hook_config_test']); unset($GLOBALS['hook_config_test']);
// Set up the ConfigImporter object for testing. // Set up the ConfigImporter object for testing.
$config_comparer = new StorageComparerManifest( $config_comparer = new StorageComparer(
$this->container->get('config.storage.staging'), $this->container->get('config.storage.staging'),
$this->container->get('config.storage')); $this->container->get('config.storage')
);
$this->configImporter = new ConfigImporter( $this->configImporter = new ConfigImporter(
$config_comparer->createChangelist(), $config_comparer->createChangelist(),
$this->container->get('event_dispatcher'), $this->container->get('event_dispatcher'),
...@@ -60,6 +62,7 @@ function setUp() { ...@@ -60,6 +62,7 @@ function setUp() {
$this->container->get('plugin.manager.entity'), $this->container->get('plugin.manager.entity'),
$this->container->get('lock') $this->container->get('lock')
); );
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
} }
/** /**
...@@ -76,6 +79,21 @@ function testNoImport() { ...@@ -76,6 +79,21 @@ function testNoImport() {
$this->assertFalse(isset($GLOBALS['hook_config_test'])); $this->assertFalse(isset($GLOBALS['hook_config_test']));
} }
/**
* Tests that trying to import from an empty staging configuration directory
* fails.
*/
function testEmptyImportFails() {
try {
$this->container->get('config.storage.staging')->deleteAll();
$this->configImporter->reset()->import();
$this->assertFalse(FALSE, "ConfigImporterException not thrown, we didn't stop an empty import.");
}
catch (ConfigImporterException $e) {
$this->assertTrue(TRUE, 'ConfigImporterException thrown, successfully stopping an empty import.');
}
}
/** /**
* Tests deletion of configuration during import. * Tests deletion of configuration during import.
*/ */
...@@ -88,12 +106,13 @@ function testDeleted() { ...@@ -88,12 +106,13 @@ function testDeleted() {
$config = config($dynamic_name); $config = config($dynamic_name);
$this->assertIdentical($config->get('id'), 'dotted.default'); $this->assertIdentical($config->get('id'), 'dotted.default');
// Create an empty manifest to delete the configuration object. // Delete the file from the staging directory.
$staging->write('manifest.config_test.dynamic', array()); $staging->delete($dynamic_name);
// Import. // Import.
$this->configImporter->reset()->import(); $this->configImporter->reset()->import();
// Verify the values have disappeared. // Verify the file has been removed.
$this->assertIdentical($storage->read($dynamic_name), FALSE); $this->assertIdentical($storage->read($dynamic_name), FALSE);
$config = config($dynamic_name); $config = config($dynamic_name);
...@@ -122,8 +141,6 @@ function testNew() { ...@@ -122,8 +141,6 @@ function testNew() {
// Verify the configuration to create does not exist yet. // Verify the configuration to create does not exist yet.
$this->assertIdentical($storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.'); $this->assertIdentical($storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.');
$this->assertIdentical($staging->exists($dynamic_name), FALSE, $dynamic_name . ' not found.');
// Create new config entity. // Create new config entity.
$original_dynamic_data = array( $original_dynamic_data = array(
'id' => 'new', 'id' => 'new',
...@@ -137,11 +154,6 @@ function testNew() { ...@@ -137,11 +154,6 @@ function testNew() {
); );
$staging->write($dynamic_name, $original_dynamic_data); $staging->write($dynamic_name, $original_dynamic_data);
// Create manifest for new config entity.
$manifest_data = config('manifest.config_test.dynamic')->get();
$manifest_data[$original_dynamic_data['id']]['name'] = 'config_test.dynamic.' . $original_dynamic_data['id'];
$staging->write('manifest.config_test.dynamic', $manifest_data);
$this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.'); $this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
// Import. // Import.
...@@ -185,9 +197,6 @@ function testUpdated() { ...@@ -185,9 +197,6 @@ function testUpdated() {
$original_dynamic_data = $storage->read($dynamic_name); $original_dynamic_data = $storage->read($dynamic_name);
$original_dynamic_data['label'] = 'Updated'; $original_dynamic_data['label'] = 'Updated';
$staging->write($dynamic_name, $original_dynamic_data); $staging->write($dynamic_name, $original_dynamic_data);
// Create manifest for updated config entity.
$manifest_data = config('manifest.config_test.dynamic')->get();
$staging->write('manifest.config_test.dynamic', $manifest_data);
// Verify the active configuration still returns the default values. // Verify the active configuration still returns the default values.
$config = config($name); $config = config($name);
...@@ -219,5 +228,5 @@ function testUpdated() { ...@@ -219,5 +228,5 @@ function testUpdated() {
// Verify that there is nothing more to import. // Verify that there is nothing more to import.
$this->assertFalse($this->configImporter->hasUnprocessedChanges()); $this->assertFalse($this->configImporter->hasUnprocessedChanges());
} }
} }
...@@ -35,13 +35,6 @@ function setUp() { ...@@ -35,13 +35,6 @@ function setUp() {
function testModuleInstallation() { function testModuleInstallation() {
$default_config = 'config_test.system'; $default_config = 'config_test.system';
$default_configuration_entity = 'config_test.dynamic.dotted.default'; $default_configuration_entity = 'config_test.dynamic.dotted.default';
$default_config_manifest = 'manifest.config_test.dynamic';
$expected_manifest_data = array(
'dotted.default' => array(
'name' => 'config_test.dynamic.dotted.default',
),
);
$default_empty_config_manifest = 'manifest.config_test.empty_manifest';
// Verify that default module config does not exist before installation yet. // Verify that default module config does not exist before installation yet.
$config = config($default_config); $config = config($default_config);
...@@ -49,12 +42,6 @@ function testModuleInstallation() { ...@@ -49,12 +42,6 @@ function testModuleInstallation() {
$config = config($default_configuration_entity); $config = config($default_configuration_entity);
$this->assertIdentical($config->isNew(), TRUE); $this->assertIdentical($config->isNew(), TRUE);
// Verify that configuration entity manifests do not exist.
$config = config($default_config_manifest);
$this->assertIdentical($config->isNew(), TRUE);
$config = config($default_empty_config_manifest);
$this->assertIdentical($config->isNew(), TRUE);
// Install the test module. // Install the test module.
$this->enableModules(array('config_test')); $this->enableModules(array('config_test'));
$this->installConfig(array('config_test')); $this->installConfig(array('config_test'));
...@@ -65,13 +52,6 @@ function testModuleInstallation() { ...@@ -65,13 +52,6 @@ function testModuleInstallation() {
$config = config($default_configuration_entity); $config = config($default_configuration_entity);
$this->assertIdentical($config->isNew(), FALSE); $this->assertIdentical($config->isNew(), FALSE);
// Verify that configuration entity manifests have been created with
// expected contents.
$config = config($default_config_manifest);
$this->assertIdentical($config->get(), $expected_manifest_data);
$config = config($default_empty_config_manifest);
$this->assertIdentical($config->get(), array());
// Verify that configuration import callback was invoked for the dynamic // Verify that configuration import callback was invoked for the dynamic
// configuration entity. // configuration entity.
$this->assertTrue($GLOBALS['hook_config_import']); $this->assertTrue($GLOBALS['hook_config_import']);
......
<?php
/**
* @file
* Definition of Drupal\config_test\Plugin\Core\Entity\ConfigTestEmptyManifest.
*/
namespace Drupal\config_test\Plugin\Core\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\Annotation\EntityType;
use Drupal\Core\Annotation\Translation;
/**
* Defines the ConfigTestEmptyManifest configuration entity.
*
* @EntityType(
* id = "config_test_empty_manifest",
* label = @Translation("Test empty manifest creation"),
* module = "config_test",
* controllers = {
* "storage" = "Drupal\config_test\ConfigTestStorageController"
* },
* config_prefix = "config_test.empty_manifest",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "uuid" = "uuid"
* }
* )
*/
class ConfigTestEmptyManifest extends ConfigEntityBase {
/**
* The machine name for the configuration entity.
*
* @var string
*/
public $id;
/**
* The UUID for the configuration entity.
*
* @var string
*/
public $uuid;
/**
* The human-readable name of the configuration entity.
*
* @var string
*/
public $label;
}
...@@ -56,12 +56,9 @@ function contact_update_8000() { ...@@ -56,12 +56,9 @@ function contact_update_8000() {
function contact_update_8001() { function contact_update_8001() {
$uuid = new Uuid(); $uuid = new Uuid();
$result = db_query('SELECT * FROM {contact}'); $result = db_query('SELECT * FROM {contact}');
$ids = array();
foreach ($result as $category) { foreach ($result as $category) {
// Take over the category's serial ID as new machine name. // Take over the category's serial ID as new machine name.
$category->id = $category->cid; $category->id = $category->cid;
// Save the id to add to the manifest file.
$ids[] = $category->id;
// Save default category setting. // Save default category setting.
if ($category->selected) { if ($category->selected) {
config('contact.settings') config('contact.settings')
...@@ -79,8 +76,6 @@ function contact_update_8001() { ...@@ -79,8 +76,6 @@ function contact_update_8001() {
->set('langcode', Language::LANGCODE_NOT_SPECIFIED) ->set('langcode', Language::LANGCODE_NOT_SPECIFIED)
->save(); ->save();
} }
update_config_manifest_add('contact.category', $ids);
} }
/** /**
......
...@@ -64,10 +64,6 @@ public function testContactUpgrade() { ...@@ -64,10 +64,6 @@ public function testContactUpgrade() {
// Check that no default config imported on upgrade. // Check that no default config imported on upgrade.
$this->assertFalse(entity_load('contact_category', 'feedback')); $this->assertFalse(entity_load('contact_category', 'feedback'));
// Assert that manifest has been created and contains the expected records.
$manifest = config('manifest.contact.category');
$this->assertEqual($manifest->get('1.name'), 'contact.category.1');
$this->assertEqual($manifest->get('2.name'), 'contact.category.2');
} }
} }
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