Commit 81666e2b authored by webchick's avatar webchick

Issue #1716920 by Albert Volkman: Fixed override example documentation needs updating.

parent a3eade7c
<?php
/**
* @file
* Admin page callbacks for the config module.
*/
use Drupal\Core\Config\StorageInterface;
/**
* Helper function to construct the storage changes in a configuration synchronization form.
*
* @param array $form
* The form structure to add to. Passed by reference.
* @param array $form_state
* The current state of the form. Passed by reference.
* @param Drupal\Core\Config\StorageInterface $source_storage
* The source storage to retrieve differences from.
* @param Drupal\Core\Config\StorageInterface $target_storage
* The target storage to compare differences to.
*/
function config_admin_sync_form(array &$form, array &$form_state, StorageInterface $source_storage, StorageInterface $target_storage) {
$config_changes = config_sync_get_changes($source_storage, $target_storage);
if (empty($config_changes)) {
$form['no_changes'] = array(
'#markup' => t('There are no configuration changes.'),
);
return $form;
}
foreach ($config_changes as $config_change_type => $config_files) {
if (empty($config_files)) {
continue;
}
// @todo A table caption would be more appropriate, but does not have the
// visual importance of a heading.
$form[$config_change_type]['heading'] = array(
'#theme' => 'html_tag__h3',
'#tag' => 'h3',
);
switch ($config_change_type) {
case 'create':
$form[$config_change_type]['heading']['#value'] = format_plural(count($config_files), '@count new', '@count new');
break;
case 'change':
$form[$config_change_type]['heading']['#value'] = format_plural(count($config_files), '@count changed', '@count changed');
break;
case 'delete':
$form[$config_change_type]['heading']['#value'] = format_plural(count($config_files), '@count removed', '@count removed');
break;
}
$form[$config_change_type]['list'] = array(
'#theme' => 'table',
'#header' => array('Name'),
);
foreach ($config_files as $config_file) {
$form[$config_change_type]['list']['#rows'][] = array($config_file);
}
}
}
/**
* Form constructor for configuration import form.
*
* @see config_admin_import_form_submit()
* @see config_import()
*/
function config_admin_import_form($form, &$form_state) {
// Retrieve a list of differences between last known state and active store.
$source_storage = drupal_container()->get('config.storage.staging');
$target_storage = drupal_container()->get('config.storage');
// Prevent users from deleting all configuration.
// If the source storage is empty, that signals the unique condition of not
// having exported anything at all, and thus no valid storage to compare the
// active storage against.
// @todo StorageInterface::listAll() can easily yield hundreds or even
// thousands of entries; consider to add a dedicated isEmpty() method for
// storage controllers.
$all = $source_storage->listAll();
if (empty($all)) {
form_set_error('', t('There is no base configuration. <a href="@export-url">Export</a> it first.', array(
'@export-url' => url('admin/config/development/sync/export'),
)));
return $form;
}
config_admin_sync_form($form, $form_state, $source_storage, $target_storage);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Import all'),
);
return $form;
}
/**
* Form submission handler for config_admin_import_form().
*/
function config_admin_import_form_submit($form, &$form_state) {
if (config_import()) {
drupal_set_message(t('The configuration was imported successfully.'));
}
else {
// Another request may be synchronizing configuration already. Wait for it
// to complete before returning the error, so already synchronized changes
// do not appear again.
lock_wait(__FUNCTION__);
drupal_set_message(t('The import failed due to an error. Any errors have been logged.'), 'error');
}
}
/**
* Form constructor for configuration export form.
*
* @see config_admin_export_form_submit()
* @see config_export()
*
* @todo "export" is a misnomer with config.storage.staging.
*/
function config_admin_export_form($form, &$form_state) {
// Retrieve a list of differences between active store and last known state.
$source_storage = drupal_container()->get('config.storage');
$target_storage = drupal_container()->get('config.storage.staging');
config_admin_sync_form($form, $form_state, $source_storage, $target_storage);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Export all'),
);
return $form;
}
/**
* Form submission handler for config_admin_export_form().
*/
function config_admin_export_form_submit($form, &$form_state) {
config_export();
drupal_set_message(t('The configuration was exported successfully.'));
}
......@@ -3,3 +3,4 @@ description = Allows administrators to manage configuration changes.
package = Core
version = VERSION
core = 8.x
configure = admin/config/development/sync
<?php
/**
* @file
* Allows site administrators to modify configuration.
*/
/**
* Implements hook_help().
*/
function config_help($path, $arg) {
switch ($path) {
case 'admin/help#config':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Configuration manager module provides a user interface for importing and exporting configuration changes; i.e., for staging configuration data between multiple instances of this web site. For more information, see the online handbook entry for <a href="!url">Configuration manager module</a>', array(
'!url' => 'http://drupal.org/documentation/modules/config',
)) . '</p>';
return $output;
case 'admin/config/development/sync':
$output = '';
$output .= '<p>' . t('Import configuration that is placed in <code>@staging-filepath</code>. All changes, deletions, renames, and additions are listed below.', array(
'@staging-filepath' => config_get_config_directory(CONFIG_STAGING_DIRECTORY),
)) . '</p>';
return $output;
}
}
/**
* Implements hook_permission().
*/
function config_permission() {
$permissions['synchronize configuration'] = array(
'title' => t('Synchronize configuration'),
'restrict access' => TRUE,
);
return $permissions;
}
/**
* Implements hook_menu().
*/
function config_menu() {
$items['admin/config/development/sync'] = array(
'title' => 'Synchronize configuration',
'description' => 'Synchronize configuration changes.',
'page callback' => 'drupal_get_form',
'page arguments' => array('config_admin_import_form'),
'access arguments' => array('synchronize configuration'),
'file' => 'config.admin.inc',
);
$items['admin/config/development/sync/import'] = array(
'title' => 'Import',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/config/development/sync/export'] = array(
'title' => 'Export',
'page callback' => 'drupal_get_form',
'page arguments' => array('config_admin_export_form'),
'access arguments' => array('synchronize configuration'),
'file' => 'config.admin.inc',
'type' => MENU_LOCAL_TASK,
);
return $items;
}
<?php
/**
* @file
* Definition of Drupal\config\Tests\ConfigImportUITest.
*/
namespace Drupal\config\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests importing configuration from files into active store.
*/
class ConfigImportUITest extends WebTestBase {
public static $modules = array('config', 'config_test');
public static function getInfo() {
return array(
'name' => 'Import/Export UI',
'description' => 'Tests the user interface for importing/exporting configuration.',
'group' => 'Configuration',
);
}
function setUp() {
parent::setUp();
$this->web_user = $this->drupalCreateUser(array('synchronize configuration'));
$this->drupalLogin($this->web_user);
}
/**
* Tests exporting configuration.
*/
function testExport() {
$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');
// Verify that both appear as deleted by default.
$this->drupalGet('admin/config/development/sync/export');
$this->assertText($name);
$this->assertText($dynamic_name);
// Export and verify that both do not appear anymore.
$this->drupalPost(NULL, array(), t('Export all'));
$this->assertUrl('admin/config/development/sync/export');
$this->assertNoText($name);
$this->assertNoText($dynamic_name);
// Verify that there are no further changes to export.
$this->assertText(t('There are no configuration changes.'));
// Verify that the import screen shows no changes either.
$this->drupalGet('admin/config/development/sync');
$this->assertText(t('There are no configuration changes.'));
}
/**
* Tests importing configuration.
*/
function testImport() {
$name = 'config_test.new';
$dynamic_name = 'config_test.dynamic.new';
$storage = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging');
// Verify the configuration to create does not exist yet.
$this->assertIdentical($storage->exists($name), FALSE, $name . ' not found.');
$this->assertIdentical($storage->exists($dynamic_name), FALSE, $dynamic_name . ' not found.');
$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 does not allow to import without exported
// configuration.
$this->drupalGet('admin/config/development/sync');
$this->assertText('There is no base configuration.');
// Verify that the Export link yields to the export UI page, and export.
$this->clickLink('Export');
$this->drupalPost(NULL, array(), t('Export all'));
// Create new configuration objects.
$original_name_data = array(
'add_me' => 'new value',
);
$staging->write($name, $original_name_data);
$original_dynamic_data = array(
'id' => 'new',
'label' => 'New',
'langcode' => 'und',
'style' => '',
'uuid' => '30df59bd-7b03-4cf7-bb35-d42fc49f0651',
);
$staging->write($dynamic_name, $original_dynamic_data);
$this->assertIdentical($staging->exists($name), TRUE, $name . ' found.');
$this->assertIdentical($staging->exists($dynamic_name), TRUE, $dynamic_name . ' found.');
// Verify that both appear as new.
$this->drupalGet('admin/config/development/sync');
$this->assertText($name);
$this->assertText($dynamic_name);
// Import and verify that both do not appear anymore.
$this->drupalPost(NULL, array(), t('Import all'));
$this->assertUrl('admin/config/development/sync');
$this->assertNoText($name);
$this->assertNoText($dynamic_name);
// Verify that there are no further changes to import.
$this->assertText(t('There are no configuration changes.'));
// Verify that the export screen shows no changes either.
$this->drupalGet('admin/config/development/sync/export');
$this->assertText(t('There are no configuration changes.'));
}
/**
* Tests concurrent importing of configuration.
*/
function testImportLock() {
$name = 'config_test.new';
$staging = $this->container->get('config.storage.staging');
// Write a configuration object to import.
$staging->write($name, array(
'add_me' => 'new value',
));
// Verify that there are configuration differences to import.
$this->drupalGet('admin/config/development/sync');
$this->assertNoText(t('There are no configuration changes.'));
// Acquire a fake-lock on the import mechanism.
$lock_name = 'config_import';
lock_acquire($lock_name);
// Attempt to import configuration and verify that an error message appears.
$this->drupalPost(NULL, array(), t('Import all'));
$this->assertUrl('admin/config/development/sync');
$this->assertText(t('The import failed due to an error. Any errors have been logged.'));
// Release the lock, just to keep testing sane.
lock_release($lock_name);
}
}
......@@ -6,6 +6,7 @@ dependencies[] = node
dependencies[] = block
dependencies[] = color
dependencies[] = comment
dependencies[] = config
dependencies[] = contextual
dependencies[] = help
dependencies[] = image
......
......@@ -363,7 +363,7 @@
* - anonymous: Defines the human-readable name of anonymous users.
* Remove the leading hash signs to enable.
*/
# $conf['site_name'] = 'My Drupal site';
# $conf['system.site']['name'] = 'My Drupal site';
# $conf['theme_default'] = 'stark';
# $conf['anonymous'] = 'Visitor';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment