contrib modules updates
This commit is contained in:
@@ -5,8 +5,8 @@ description: 'Provides basic revert and update functionality for other modules'
|
||||
dependencies:
|
||||
- drupal:config
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-05
|
||||
version: '8.x-1.5'
|
||||
# Information added by Drupal.org packaging script on 2018-12-17
|
||||
version: '8.x-1.6'
|
||||
core: '8.x'
|
||||
project: 'config_update'
|
||||
datestamp: 1512514387
|
||||
datestamp: 1545090489
|
||||
|
||||
+6
-1
@@ -285,8 +285,13 @@ function drush_config_update_ui_config_revert($name) {
|
||||
|
||||
// The revert command needs the type and the unprefixed name.
|
||||
$type = $lister->getTypeNameByConfigName($name);
|
||||
// The lister gives NULL if simple configuration, but the reverter expects
|
||||
// 'system.simple' so we convert it.
|
||||
if ($type === NULL) {
|
||||
$type = 'system.simple';
|
||||
}
|
||||
$shortname = $name;
|
||||
if ($type && $type != 'system.simple') {
|
||||
if ($type != 'system.simple') {
|
||||
$definition = $manager->getDefinition($type);
|
||||
$prefix = $definition->getConfigPrefix() . '.';
|
||||
if (strpos($name, $prefix) === 0) {
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ dependencies:
|
||||
- config_update:config_update
|
||||
- drupal:config
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-05
|
||||
version: '8.x-1.5'
|
||||
# Information added by Drupal.org packaging script on 2018-12-17
|
||||
version: '8.x-1.6'
|
||||
core: '8.x'
|
||||
project: 'config_update'
|
||||
datestamp: 1512514387
|
||||
datestamp: 1545090489
|
||||
|
||||
+17
@@ -35,3 +35,20 @@ function config_update_ui_help($route_name, RouteMatchInterface $route_match) {
|
||||
return '<p>' . t('Most configuration is organized into a hierarchy of settings; at a minimum, it is a one-level hierarchy where each setting has a name and a value, and the hierarchy comes in when some of the settings have multiple components.') . '</p><p>' . t('Configuration items are normalized and formatted before computing differences. The normalization step alphabetizes the components at each level of the hierarchy, and removes a few components whose differences should be ignored, such as the UUID. The formatting step shows the full hierarchy of each configuration value with :: separators for the hierarchy levels, and a : separator between the lowest-level setting name and the value, so that in a line-by-line diff you can always see which values are actually different. Green lines with + signs have been added, and yellow lines with - signs have been removed.') . '</p><p>' . t('Note that differences are considering the base configuration, without overrides from your settings.php file, or translations.') . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_links_discovered_alter().
|
||||
*/
|
||||
function config_update_ui_menu_links_discovered_alter(&$links) {
|
||||
if (\Drupal::moduleHandler()->moduleExists('admin_toolbar_tools')) {
|
||||
// Add the Updates report link to the Tools menu, but only if the
|
||||
// Admin Toolbar Extra Tools module is present.
|
||||
$links['admin_toolbar_tools.config.update'] = [
|
||||
'title' => t('Updates report'),
|
||||
'route_name' => 'config_update_ui.report',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'config.sync',
|
||||
'weight' => 3,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ class ConfigDeleteConfirmForm extends ConfirmFormBase {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->configRevert->delete($this->type, $this->name);
|
||||
|
||||
drupal_set_message($this->t('The configuration was deleted.'));
|
||||
$this->messenger()->addMessage($this->t('The configuration %item has been deleted.', ['%item' => $this->name]));
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ class ConfigImportConfirmForm extends ConfirmFormBase {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->configRevert->import($this->type, $this->name);
|
||||
|
||||
drupal_set_message($this->t('The configuration was imported from its source.'));
|
||||
$this->messenger()->addMessage($this->t('The configuration %item has been imported from its source.', ['%item' => $this->name]));
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ class ConfigRevertConfirmForm extends ConfirmFormBase {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->configRevert->revert($this->type, $this->name);
|
||||
|
||||
drupal_set_message($this->t('The configuration was reverted to its source.'));
|
||||
$this->messenger()->addMessage($this->t('The configuration %item has been reverted to its source.', ['%item' => $this->name]));
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
|
||||
|
||||
+14
-10
@@ -1,15 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\config_update_ui\Tests;
|
||||
namespace Drupal\Tests\config_update_ui\Functional;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Verify config reports, reverts, and diffs with profile overrides.
|
||||
*
|
||||
* @group config
|
||||
* @group config_update
|
||||
*/
|
||||
class ConfigProfileOverridesTest extends WebTestBase {
|
||||
class ConfigProfileOverridesTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Use the Standard profile, so that there are profile config overrides.
|
||||
@@ -43,7 +43,7 @@ class ConfigProfileOverridesTest extends WebTestBase {
|
||||
parent::setUp();
|
||||
|
||||
// Create user and log in.
|
||||
$this->adminUser = $this->drupalCreateUser([
|
||||
$this->adminUser = $this->createUser([
|
||||
'access administration pages',
|
||||
'administer themes',
|
||||
'view config updates report',
|
||||
@@ -68,7 +68,8 @@ class ConfigProfileOverridesTest extends WebTestBase {
|
||||
// that system.theme is not shown (it should not be missing, or added,
|
||||
// or overridden).
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/system.simple');
|
||||
$this->assertNoRaw('system.theme');
|
||||
$session = $this->assertSession();
|
||||
$session->responseNotContains('system.theme');
|
||||
|
||||
// Go to the Appearance page and change the theme to whatever is currently
|
||||
// disabled. Return to the report and verify that system.theme is there,
|
||||
@@ -76,22 +77,25 @@ class ConfigProfileOverridesTest extends WebTestBase {
|
||||
$this->drupalGet('admin/appearance');
|
||||
$this->clickLink('Install and set as default');
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/system.simple');
|
||||
$this->assertText('system.theme');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('system.theme');
|
||||
|
||||
// Look at the differences for system.theme and verify it's against
|
||||
// the standard profile version, not default version. The line for
|
||||
// default should show bartik as the source; if it's against the system
|
||||
// version, the word bartik would not be there.
|
||||
$this->drupalGet('admin/config/development/configuration/report/diff/system.simple/system.theme');
|
||||
$this->assertText('bartik');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('bartik');
|
||||
|
||||
// Revert and verify that it reverted to the profile version, not the
|
||||
// system module version.
|
||||
$this->drupalGet('admin/config/development/configuration/report/revert/system.simple/system.theme');
|
||||
$this->drupalPostForm(NULL, [], 'Revert');
|
||||
$this->drupalGet('admin/config/development/configuration/single/export/system.simple/system.theme');
|
||||
$this->assertText('admin: seven');
|
||||
$this->assertText('default: bartik');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('admin: seven');
|
||||
$session->pageTextContains('default: bartik');
|
||||
}
|
||||
|
||||
}
|
||||
+120
-97
@@ -1,15 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\config_update_ui\Tests;
|
||||
namespace Drupal\Tests\config_update_ui\Functional;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Verify the config revert report and its links.
|
||||
*
|
||||
* @group config
|
||||
* @group config_update
|
||||
*/
|
||||
class ConfigUpdateTest extends WebTestBase {
|
||||
class ConfigUpdateTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
@@ -46,7 +46,7 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
parent::setUp();
|
||||
|
||||
// Create user and log in.
|
||||
$this->adminUser = $this->drupalCreateUser([
|
||||
$this->adminUser = $this->createUser([
|
||||
'access administration pages',
|
||||
'administer search',
|
||||
'view config updates report',
|
||||
@@ -60,8 +60,8 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Make sure local tasks and page title are showing.
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
$this->placeBlock('local_tasks_block');
|
||||
$this->placeBlock('page_title_block');
|
||||
|
||||
// Load the Drush include file so that its functions can be tested, plus
|
||||
// the Drush testing include file.
|
||||
@@ -103,13 +103,15 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
$this->assertReport('Testing profile', [], [], [], $inactive, ['added']);
|
||||
// The locale.settings line should show that the Testing profile is the
|
||||
// provider.
|
||||
$this->assertText('Testing profile');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Testing profile');
|
||||
$this->assertDrushReports('profile', '', [], [], [], array_keys($inactive));
|
||||
|
||||
// Verify that the user search page cannot be imported (because it already
|
||||
// exists).
|
||||
$this->drupalGet('admin/config/development/configuration/report/import/search_page/user_search');
|
||||
$this->assertResponse(404);
|
||||
$session = $this->assertSession();
|
||||
$session->statusCodeEquals(404);
|
||||
|
||||
// Delete the user search page from the search UI and verify report for
|
||||
// both the search page config type and user module.
|
||||
@@ -121,7 +123,8 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
$this->assertReport('Search page', [], [], [], $inactive);
|
||||
// The search.page.user_search line should show that the User module is the
|
||||
// provider.
|
||||
$this->assertText('User module');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('User module');
|
||||
$this->assertDrushReports('type', 'search_page', [], [], [], array_keys($inactive));
|
||||
|
||||
$this->drupalGet('admin/config/development/configuration/report/module/user');
|
||||
@@ -138,17 +141,20 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
// Verify that the user search page cannot be reverted (because it does
|
||||
// not already exist).
|
||||
$this->drupalGet('admin/config/development/configuration/report/revert/search_page/user_search');
|
||||
$this->assertResponse(404);
|
||||
$session = $this->assertSession();
|
||||
$session->statusCodeEquals(404);
|
||||
// Verify that the delete URL doesn't work either.
|
||||
$this->drupalGet('admin/config/development/configuration/report/delete/search_page/user_search');
|
||||
$this->assertResponse(404);
|
||||
$session = $this->assertSession();
|
||||
$session->statusCodeEquals(404);
|
||||
|
||||
// Use the import link to get it back. Do this from the search page
|
||||
// report to make sure we are importing the right config.
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->clickLink('Import from source');
|
||||
$this->drupalPostForm(NULL, [], 'Import');
|
||||
$this->assertText('The configuration was imported');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('has been imported');
|
||||
$this->assertNoReport();
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->assertReport('Search page', [], [], [], []);
|
||||
@@ -156,8 +162,9 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
// Verify that after import, there is no config hash generated.
|
||||
$this->drupalGet('admin/config/development/configuration/single/export/search_page/user_search');
|
||||
$this->assertText('id: user_search');
|
||||
$this->assertNoText('default_config_hash:');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('id: user_search');
|
||||
$session->pageTextNotContains('default_config_hash:');
|
||||
|
||||
// Test importing again, this time using the Drush import command.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
@@ -184,10 +191,11 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
// Test the show differences link.
|
||||
$this->clickLink('Show differences');
|
||||
$this->assertText('Content');
|
||||
$this->assertText('New label');
|
||||
$this->assertText('node');
|
||||
$this->assertText('new_path');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Content');
|
||||
$session->pageTextContains('New label');
|
||||
$session->pageTextContains('node');
|
||||
$session->pageTextContains('new_path');
|
||||
|
||||
// Test the show differences Drush command.
|
||||
$output = drush_config_update_ui_config_diff('search.page.node_search');
|
||||
@@ -203,36 +211,39 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
// Test the export link.
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->clickLink('Export');
|
||||
$this->assertText('Here is your configuration:');
|
||||
$this->assertText('id: node_search');
|
||||
$this->assertText('New label');
|
||||
$this->assertText('path: new_path');
|
||||
$this->assertText('search.page.node_search.yml');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Here is your configuration:');
|
||||
$session->pageTextContains('id: node_search');
|
||||
$session->pageTextContains('New label');
|
||||
$session->pageTextContains('path: new_path');
|
||||
$session->pageTextContains('search.page.node_search.yml');
|
||||
|
||||
// Grab the uuid and hash lines for the next test.
|
||||
$text = $this->getTextContent();
|
||||
// Grab the uuid and hash lines from the exported config for the next test.
|
||||
$text = strip_tags($this->getSession()->getPage()->find('css', 'textarea')->getHtml());
|
||||
$matches = [];
|
||||
preg_match('|^.*uuid:.*$|m', $text, $matches);
|
||||
$uuid_line = $matches[0];
|
||||
$uuid_line = trim($matches[0]);
|
||||
preg_match('|^.*default_config_hash:.*$|m', $text, $matches);
|
||||
$hash_line = $matches[0];
|
||||
$hash_line = trim($matches[0]);
|
||||
|
||||
// Test reverting.
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->clickLink('Revert to source');
|
||||
$this->assertText('Are you sure you want to revert');
|
||||
$this->assertText('Search page');
|
||||
$this->assertText('node_search');
|
||||
$this->assertText('Customizations will be lost. This action cannot be undone');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Are you sure you want to revert');
|
||||
$session->pageTextContains('Search page');
|
||||
$session->pageTextContains('node_search');
|
||||
$session->pageTextContains('Customizations will be lost. This action cannot be undone');
|
||||
$this->drupalPostForm(NULL, [], 'Revert');
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->assertReport('Search page', [], [], [], []);
|
||||
|
||||
// Verify that the uuid and hash keys were retained in the revert.
|
||||
$this->drupalGet('admin/config/development/configuration/single/export/search_page/node_search');
|
||||
$this->assertText('id: node_search');
|
||||
$this->assertText($uuid_line);
|
||||
$this->assertText($hash_line);
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('id: node_search');
|
||||
$session->pageTextContains($uuid_line);
|
||||
$session->pageTextContains($hash_line);
|
||||
|
||||
// Test reverting again, this time using Drush single revert command.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
@@ -278,19 +289,22 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
// Test the export link.
|
||||
$this->clickLink('Export');
|
||||
$this->assertText('Here is your configuration:');
|
||||
$this->assertText('id: test');
|
||||
$this->assertText('label: test');
|
||||
$this->assertText('path: test');
|
||||
$this->assertText('search.page.test.yml');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Here is your configuration:');
|
||||
$session->pageTextContains('id: test');
|
||||
$session->pageTextContains('label: test');
|
||||
$session->pageTextContains('path: test');
|
||||
$session->pageTextContains('search.page.test.yml');
|
||||
|
||||
// Test the delete link.
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
$this->clickLink('Delete');
|
||||
$this->assertText('Are you sure');
|
||||
$this->assertText('cannot be undone');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Are you sure');
|
||||
$session->pageTextContains('cannot be undone');
|
||||
$this->drupalPostForm(NULL, [], 'Delete');
|
||||
$this->assertText('The configuration was deleted');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('has been deleted');
|
||||
|
||||
// And verify the report again.
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
|
||||
@@ -306,18 +320,20 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
$this->assertReport('Search module', [], [], $changed, [], ['added']);
|
||||
|
||||
$this->clickLink('Show differences');
|
||||
$this->assertText('Config difference for Simple configuration search.settings');
|
||||
$this->assertText('index::minimum_word_size');
|
||||
$this->assertText('4');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Config difference for Simple configuration search.settings');
|
||||
$session->pageTextContains('index::minimum_word_size');
|
||||
$session->pageTextContains('4');
|
||||
|
||||
$this->drupalGet('admin/config/development/configuration/report/module/search');
|
||||
$this->clickLink('Export');
|
||||
$this->assertText('minimum_word_size: 4');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('minimum_word_size: 4');
|
||||
// Grab the hash line for the next test.
|
||||
$text = $this->getTextContent();
|
||||
$text = strip_tags($this->getSession()->getPage()->find('css', 'textarea')->getHtml());
|
||||
$matches = [];
|
||||
preg_match('|^.*default_config_hash:.*$|m', $text, $matches);
|
||||
$hash_line = $matches[0];
|
||||
$hash_line = trim($matches[0]);
|
||||
|
||||
$this->drupalGet('admin/config/development/configuration/report/module/search');
|
||||
$this->clickLink('Revert to source');
|
||||
@@ -325,7 +341,8 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
// Verify that the hash was retained in the revert.
|
||||
$this->drupalGet('admin/config/development/configuration/single/export/system.simple/search.settings');
|
||||
$this->assertText($hash_line);
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains($hash_line);
|
||||
|
||||
$this->drupalGet('admin/config/development/configuration/report/module/search');
|
||||
$this->assertReport('Search module', [], [], [], [], ['added']);
|
||||
@@ -338,6 +355,10 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
$changed = ['filter.format.plain_text' => 'New label'];
|
||||
$this->drupalGet('admin/config/development/configuration/report/type/filter_format');
|
||||
$this->assertReport('Text format', [], [], $changed, []);
|
||||
|
||||
// Verify that we can revert non-entity configuration in Drush. Issue:
|
||||
// https://www.drupal.org/project/config_update/issues/2935395
|
||||
drush_config_update_ui_config_revert('system.date');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,62 +380,63 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
* Array of report sections to skip checking.
|
||||
*/
|
||||
protected function assertReport($title, array $missing, array $added, array $changed, array $inactive, array $skip = []) {
|
||||
$this->assertText('Configuration updates report for ' . $title);
|
||||
$this->assertText('Generate new report');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Configuration updates report for ' . $title);
|
||||
$session->pageTextContains('Generate new report');
|
||||
|
||||
if (!in_array('missing', $skip)) {
|
||||
$this->assertText('Missing configuration items');
|
||||
$session->pageTextContains('Missing configuration items');
|
||||
if (count($missing)) {
|
||||
foreach ($missing as $name => $label) {
|
||||
$this->assertText($name);
|
||||
$this->assertText($label);
|
||||
$session->pageTextContains($name);
|
||||
$session->pageTextContains($label);
|
||||
}
|
||||
$this->assertNoText('None: all provided configuration items are in your active configuration.');
|
||||
$session->pageTextNotContains('None: all provided configuration items are in your active configuration.');
|
||||
}
|
||||
else {
|
||||
$this->assertText('None: all provided configuration items are in your active configuration.');
|
||||
$session->pageTextContains('None: all provided configuration items are in your active configuration.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array('inactive', $skip)) {
|
||||
$this->assertText('Inactive optional items');
|
||||
$session->pageTextContains('Inactive optional items');
|
||||
if (count($inactive)) {
|
||||
foreach ($inactive as $name => $label) {
|
||||
$this->assertText($name);
|
||||
$this->assertText($label);
|
||||
$session->pageTextContains($name);
|
||||
$session->pageTextContains($label);
|
||||
}
|
||||
$this->assertNoText('None: all optional configuration items are in your active configuration.');
|
||||
$session->pageTextNotContains('None: all optional configuration items are in your active configuration.');
|
||||
}
|
||||
else {
|
||||
$this->assertText('None: all optional configuration items are in your active configuration.');
|
||||
$session->pageTextContains('None: all optional configuration items are in your active configuration.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array('added', $skip)) {
|
||||
$this->assertText('Added configuration items');
|
||||
$session->pageTextContains('Added configuration items');
|
||||
if (count($added)) {
|
||||
foreach ($added as $name => $label) {
|
||||
$this->assertText($name);
|
||||
$this->assertText($label);
|
||||
$session->pageTextContains($name);
|
||||
$session->pageTextContains($label);
|
||||
}
|
||||
$this->assertNoText('None: all active configuration items of this type were provided by modules, themes, or install profile.');
|
||||
$session->pageTextNotContains('None: all active configuration items of this type were provided by modules, themes, or install profile.');
|
||||
}
|
||||
else {
|
||||
$this->assertText('None: all active configuration items of this type were provided by modules, themes, or install profile.');
|
||||
$session->pageTextContains('None: all active configuration items of this type were provided by modules, themes, or install profile.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array('changed', $skip)) {
|
||||
$this->assertText('Changed configuration items');
|
||||
$session->pageTextContains('Changed configuration items');
|
||||
if (count($changed)) {
|
||||
foreach ($changed as $name => $label) {
|
||||
$this->assertText($name);
|
||||
$this->assertText($label);
|
||||
$session->pageTextContains($name);
|
||||
$session->pageTextContains($label);
|
||||
}
|
||||
$this->assertNoText('None: no active configuration items differ from their current provided versions.');
|
||||
$session->pageTextNotContains('None: no active configuration items differ from their current provided versions.');
|
||||
}
|
||||
else {
|
||||
$this->assertText('None: no active configuration items differ from their current provided versions.');
|
||||
$session->pageTextContains('None: no active configuration items differ from their current provided versions.');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -440,7 +462,7 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
protected function assertDrushReports($type, $name, array $missing, array $added, array $changed, array $inactive, array $skip = []) {
|
||||
if (!in_array('missing', $skip)) {
|
||||
$output = drush_config_update_ui_config_missing_report($type, $name);
|
||||
$this->assertEqual(count($output), count($missing), 'Drush missing report has correct number of items');
|
||||
$this->assertEquals(count($output), count($missing), 'Drush missing report has correct number of items');
|
||||
if (count($missing)) {
|
||||
foreach ($missing as $item) {
|
||||
$this->assertTrue(in_array($item, $output), "Item $item is in the Drush missing report");
|
||||
@@ -450,7 +472,7 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
if (!in_array('added', $skip) && $type == 'type') {
|
||||
$output = drush_config_update_ui_config_added_report($name);
|
||||
$this->assertEqual(count($output), count($added), 'Drush added report has correct number of items');
|
||||
$this->assertEquals(count($output), count($added), 'Drush added report has correct number of items');
|
||||
if (count($added)) {
|
||||
foreach ($added as $item) {
|
||||
$this->assertTrue(in_array($item, $output), "Item $item is in the Drush added report");
|
||||
@@ -460,7 +482,7 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
if (!in_array('changed', $skip)) {
|
||||
$output = drush_config_update_ui_config_different_report($type, $name);
|
||||
$this->assertEqual(count($output), count($changed), 'Drush changed report has correct number of items');
|
||||
$this->assertEquals(count($output), count($changed), 'Drush changed report has correct number of items');
|
||||
if (count($changed)) {
|
||||
foreach ($changed as $item) {
|
||||
$this->assertTrue(in_array($item, $output), "Item $item is in the Drush changed report");
|
||||
@@ -470,7 +492,7 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
|
||||
if (!in_array('inactive', $skip)) {
|
||||
$output = drush_config_update_ui_config_inactive_report($type, $name);
|
||||
$this->assertEqual(count($output), count($inactive), 'Drush inactive report has correct number of items');
|
||||
$this->assertEquals(count($output), count($inactive), 'Drush inactive report has correct number of items');
|
||||
if (count($inactive)) {
|
||||
foreach ($inactive as $item) {
|
||||
$this->assertTrue(in_array($item, $output), "Item $item is in the Drush inactive report");
|
||||
@@ -485,37 +507,38 @@ class ConfigUpdateTest extends WebTestBase {
|
||||
* Assumes you are already on the report form page.
|
||||
*/
|
||||
protected function assertNoReport() {
|
||||
$this->assertText('Report type');
|
||||
$this->assertText('Full report');
|
||||
$this->assertText('Single configuration type');
|
||||
$this->assertText('Single module');
|
||||
$this->assertText('Single theme');
|
||||
$this->assertText('Installation profile');
|
||||
$this->assertText('Updates report');
|
||||
$this->assertNoText('Missing configuration items');
|
||||
$this->assertNoText('Added configuration items');
|
||||
$this->assertNoText('Changed configuration items');
|
||||
$this->assertNoText('Unchanged configuration items');
|
||||
$session = $this->assertSession();
|
||||
$session->pageTextContains('Report type');
|
||||
$session->pageTextContains('Full report');
|
||||
$session->pageTextContains('Single configuration type');
|
||||
$session->pageTextContains('Single module');
|
||||
$session->pageTextContains('Single theme');
|
||||
$session->pageTextContains('Installation profile');
|
||||
$session->pageTextContains('Updates report');
|
||||
$session->pageTextNotContains('Missing configuration items');
|
||||
$session->pageTextNotContains('Added configuration items');
|
||||
$session->pageTextNotContains('Changed configuration items');
|
||||
$session->pageTextNotContains('Unchanged configuration items');
|
||||
|
||||
// Verify that certain report links are shown or not shown. For extensions,
|
||||
// only extensions that have configuration should be shown.
|
||||
// Modules.
|
||||
$this->assertLink('Search');
|
||||
$this->assertLink('Field');
|
||||
$this->assertNoLink('Configuration Update Base');
|
||||
$this->assertNoLink('Configuration Update Reports');
|
||||
$session->linkExists('Search');
|
||||
$session->linkExists('Field');
|
||||
$session->linkNotExists('Configuration Update Base');
|
||||
$session->linkNotExists('Configuration Update Reports');
|
||||
|
||||
// Themes.
|
||||
$this->assertNoLink('Stark');
|
||||
$this->assertNoLink('Classy');
|
||||
$session->linkNotExists('Stark');
|
||||
$session->linkNotExists('Classy');
|
||||
|
||||
// Profiles.
|
||||
$this->assertLink('Testing');
|
||||
$session->linkExists('Testing');
|
||||
|
||||
// Configuration types.
|
||||
$this->assertLink('Everything');
|
||||
$this->assertLink('Simple configuration');
|
||||
$this->assertLink('Search page');
|
||||
$session->linkExists('Everything');
|
||||
$session->linkExists('Simple configuration');
|
||||
$session->linkExists('Search page');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# This is the DrupalCI testbot build file for Configuration Update Manager.
|
||||
# Learn to make one for your own drupal.org project:
|
||||
# https://www.drupal.org/drupalorg/docs/drupal-ci/customizing-drupalci-testing
|
||||
build:
|
||||
assessment:
|
||||
validate_codebase:
|
||||
phplint:
|
||||
phpcs:
|
||||
# phpcs will use core's specified version of Coder.
|
||||
sniff-all-files: true
|
||||
halt-on-fail: true
|
||||
testing:
|
||||
# run_tests task is executed several times in order of performance speeds.
|
||||
# halt-on-fail can be set on the run_tests tasks in order to fail fast.
|
||||
# suppress-deprecations is false in order to be alerted to usages of
|
||||
# deprecated code.
|
||||
run_tests.phpunit:
|
||||
types: 'PHPUnit-Unit'
|
||||
testgroups: '--all'
|
||||
suppress-deprecations: false
|
||||
halt-on-fail: false
|
||||
run_tests.kernel:
|
||||
types: 'PHPUnit-Kernel'
|
||||
testgroups: '--all'
|
||||
suppress-deprecations: false
|
||||
halt-on-fail: false
|
||||
run_tests.functional:
|
||||
types: 'PHPUnit-Functional'
|
||||
testgroups: '--all'
|
||||
suppress-deprecations: false
|
||||
halt-on-fail: false
|
||||
run_tests.javascript:
|
||||
concurrency: 15
|
||||
types: 'PHPUnit-FunctionalJavascript'
|
||||
testgroups: '--all'
|
||||
suppress-deprecations: false
|
||||
halt-on-fail: false
|
||||
@@ -5,6 +5,7 @@ namespace Drupal\config_update;
|
||||
use Drupal\Component\Diff\Diff;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
/**
|
||||
* Provides methods related to config differences.
|
||||
@@ -14,7 +15,7 @@ class ConfigDiffer implements ConfigDiffInterface {
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* List of elements to ignore when comparing config.
|
||||
* List of elements to ignore on top level when comparing config.
|
||||
*
|
||||
* @var string[]
|
||||
*
|
||||
@@ -46,7 +47,7 @@ class ConfigDiffer implements ConfigDiffInterface {
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
|
||||
* String translation service.
|
||||
* @param string[] $ignore
|
||||
* Config components to ignore.
|
||||
* Config components to ignore at the top level.
|
||||
* @param string $hierarchy_prefix
|
||||
* Prefix to use in diffs for array hierarchy.
|
||||
* @param string $value_prefix
|
||||
@@ -62,9 +63,9 @@ class ConfigDiffer implements ConfigDiffInterface {
|
||||
/**
|
||||
* Normalizes config for comparison.
|
||||
*
|
||||
* Recursively removes elements in the ignore list from configuration,
|
||||
* as well as empty array values, and sorts at each level by array key, so
|
||||
* that config from different storage can be compared meaningfully.
|
||||
* Removes elements in the ignore list from the top level of configuration,
|
||||
* and at each level of the array, removes empty arrays and sorts by array
|
||||
* key, so that config from different storage can be compared meaningfully.
|
||||
*
|
||||
* @param array|null $config
|
||||
* Configuration array to normalize.
|
||||
@@ -80,27 +81,40 @@ class ConfigDiffer implements ConfigDiffInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Remove "ignore" elements.
|
||||
// Remove "ignore" elements, only at the top level.
|
||||
foreach ($this->ignore as $element) {
|
||||
unset($config[$element]);
|
||||
}
|
||||
|
||||
// Recursively normalize remaining elements, if they are arrays.
|
||||
foreach ($config as $key => $value) {
|
||||
// Recursively normalize and return.
|
||||
return $this->normalizeArray($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sorts an array by key, and removes empty arrays.
|
||||
*
|
||||
* @param array $array
|
||||
* An array to normalize.
|
||||
*
|
||||
* @return array
|
||||
* An array that is sorted by key, at each level of the array, with empty
|
||||
* arrays removed.
|
||||
*/
|
||||
protected function normalizeArray(array $array) {
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$new = $this->normalize($value);
|
||||
$new = $this->normalizeArray($value);
|
||||
if (count($new)) {
|
||||
$config[$key] = $new;
|
||||
$array[$key] = $new;
|
||||
}
|
||||
else {
|
||||
unset($config[$key]);
|
||||
unset($array[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort and return.
|
||||
ksort($config);
|
||||
return $config;
|
||||
ksort($array);
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,11 +171,8 @@ class ConfigDiffer implements ConfigDiffInterface {
|
||||
$lines[] = $line;
|
||||
}
|
||||
}
|
||||
elseif (is_null($value)) {
|
||||
$lines[] = $section_prefix . $this->valuePrefix . $this->t('(NULL)');
|
||||
}
|
||||
else {
|
||||
$lines[] = $section_prefix . $this->valuePrefix . $value;
|
||||
$lines[] = $section_prefix . $this->valuePrefix . Yaml::encode($value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ class ConfigLister implements ConfigListInterface {
|
||||
|
||||
// Calculate and return the list.
|
||||
foreach ($this->entityManager->getDefinitions() as $entity_type => $definition) {
|
||||
if ($definition->isSubclassOf('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
|
||||
if ($definition->entityClassImplements('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
|
||||
$this->definitions[$entity_type] = $definition;
|
||||
$prefix = $definition->getConfigPrefix();
|
||||
$this->typesByPrefix[$prefix] = $entity_type;
|
||||
|
||||
@@ -72,7 +72,7 @@ interface ConfigRevertInterface {
|
||||
* The name of the config item, without the prefix.
|
||||
*
|
||||
* @return array
|
||||
* The configuration value.
|
||||
* The configuration value, or FALSE if it is not found.
|
||||
*/
|
||||
public function getFromActive($type, $name);
|
||||
|
||||
|
||||
@@ -87,11 +87,15 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import($type, $name) {
|
||||
// Read the config from the file.
|
||||
// Read the config from the file. Note: Do not call getFromExtension() here
|
||||
// because we need $full_name below.
|
||||
$full_name = $this->getFullName($type, $name);
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
$value = FALSE;
|
||||
if ($full_name) {
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
}
|
||||
}
|
||||
if (!$value) {
|
||||
return FALSE;
|
||||
@@ -118,36 +122,44 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function revert($type, $name) {
|
||||
// Read the config from the file.
|
||||
// Read the config from the file. Note: Do not call getFromExtension() here
|
||||
// because we need $full_name below.
|
||||
$value = FALSE;
|
||||
$full_name = $this->getFullName($type, $name);
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
if ($full_name) {
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
}
|
||||
}
|
||||
if (!$value) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Make sure the configuration exists currently in active storage.
|
||||
if (!$this->activeConfigStorage->read($full_name)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Load the current config and replace the value, retaining the config
|
||||
// hash (which is part of the _core config key's value).
|
||||
if ($type == 'system.simple') {
|
||||
// Load the current config and replace the value, retaining the config
|
||||
// hash (which is part of the _core config key's value).
|
||||
$config = $this->configFactory->getEditable($full_name);
|
||||
$core = $config->get('_core');
|
||||
$config->setData($value);
|
||||
$config->set('_core', $core);
|
||||
$config->save();
|
||||
$config
|
||||
->setData($value)
|
||||
->set('_core', $core)
|
||||
->save();
|
||||
}
|
||||
else {
|
||||
// Load the current config entity and replace the value. Note that
|
||||
// the uuid and _core/hash values are retained for entity-based config,
|
||||
// since updateFromStorageRecord() only updates values that are part of
|
||||
// the passed-in array, and doesn't remove or alter other values.
|
||||
$definition = $this->entityManager->getDefinition($type);
|
||||
$id_key = $definition->getKey('id');
|
||||
$id = $value[$id_key];
|
||||
$entity_storage = $this->entityManager->getStorage($type);
|
||||
$entity = $entity_storage->load($id);
|
||||
$core = $entity->get('_core');
|
||||
$entity = $entity_storage->updateFromStorageRecord($entity, $value);
|
||||
$entity->set('_core', $core);
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
@@ -162,11 +174,15 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($type, $name) {
|
||||
$config = FALSE;
|
||||
$full_name = $this->getFullName($type, $name);
|
||||
if (!$full_name) {
|
||||
return FALSE;
|
||||
if ($full_name) {
|
||||
// Make sure the configuration exists currently in active storage.
|
||||
if (!$this->activeConfigStorage->read($full_name)) {
|
||||
return FALSE;
|
||||
}
|
||||
$config = $this->configFactory->getEditable($full_name);
|
||||
}
|
||||
$config = $this->configFactory->getEditable($full_name);
|
||||
if (!$config) {
|
||||
return FALSE;
|
||||
}
|
||||
@@ -183,17 +199,23 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
*/
|
||||
public function getFromActive($type, $name) {
|
||||
$full_name = $this->getFullName($type, $name);
|
||||
return $this->activeConfigStorage->read($full_name);
|
||||
if ($full_name) {
|
||||
return $this->activeConfigStorage->read($full_name);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFromExtension($type, $name) {
|
||||
$value = FALSE;
|
||||
$full_name = $this->getFullName($type, $name);
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
if ($full_name) {
|
||||
$value = $this->extensionConfigStorage->read($full_name);
|
||||
if (!$value) {
|
||||
$value = $this->extensionOptionalConfigStorage->read($full_name);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
@@ -207,7 +229,7 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
* The config name, without prefix.
|
||||
*
|
||||
* @return string
|
||||
* The config item's full name.
|
||||
* The config item's full name, or FALSE if there is an error.
|
||||
*/
|
||||
protected function getFullName($type, $name) {
|
||||
if ($type == 'system.simple' || !$type) {
|
||||
@@ -215,8 +237,13 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
|
||||
}
|
||||
|
||||
$definition = $this->entityManager->getDefinition($type);
|
||||
$prefix = $definition->getConfigPrefix() . '.';
|
||||
return $prefix . $name;
|
||||
if ($definition) {
|
||||
$prefix = $definition->getConfigPrefix() . '.';
|
||||
return $prefix . $name;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Drupal\Tests\config_update\Unit;
|
||||
|
||||
use Drupal\config_update\ConfigDiffer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the \Drupal\config_update\ConfigDiffer class.
|
||||
@@ -12,14 +11,7 @@ use Drupal\Tests\UnitTestCase;
|
||||
*
|
||||
* @coversDefaultClass \Drupal\config_update\ConfigDiffer
|
||||
*/
|
||||
class ConfigDifferTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mock translation object.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface
|
||||
*/
|
||||
protected $stringTranslation;
|
||||
class ConfigDifferTest extends ConfigUpdateUnitTestBase {
|
||||
|
||||
/**
|
||||
* The config differ to test.
|
||||
@@ -32,12 +24,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->stringTranslation = $this->getMockBuilder('Drupal\Core\StringTranslation\TranslationInterface')->getMock();
|
||||
$this->stringTranslation
|
||||
->method('t')
|
||||
->will($this->returnArgument(0));
|
||||
|
||||
$this->configDiffer = new ConfigDiffer($this->stringTranslation);
|
||||
$this->configDiffer = new ConfigDiffer($this->getTranslationMock());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,13 +46,14 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
];
|
||||
|
||||
return [
|
||||
[$base, $base, TRUE],
|
||||
|
||||
// Add _core, omit uuid. Should match.
|
||||
// Add _core, omit uuid at top level. Should match, as both are removed
|
||||
// in normalization process.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
@@ -75,27 +63,30 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
TRUE,
|
||||
],
|
||||
|
||||
// Change order. Should match.
|
||||
// Change order in top and deep level. Should match.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
'a' => 'a',
|
||||
'uuid' => 'bar',
|
||||
'b' => 0,
|
||||
'a' => 'a',
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
'd' => TRUE,
|
||||
],
|
||||
],
|
||||
TRUE,
|
||||
],
|
||||
|
||||
// Change order and add _core in deeper level. Should match.
|
||||
// Add _core in deeper level. Should not match, as this is removed
|
||||
// only at the top level during normalization.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
@@ -103,12 +94,31 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'a' => 'a',
|
||||
'b' => 0,
|
||||
'c' => [
|
||||
'e' => FALSE,
|
||||
'_core' => 'foo',
|
||||
'_core' => 'do-not-use-this-key',
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
TRUE,
|
||||
FALSE,
|
||||
],
|
||||
|
||||
// Add uuid in deeper level. Should not match, as this is removed
|
||||
// only at the top level during normalization.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
'uuid' => 'bar',
|
||||
'a' => 'a',
|
||||
'b' => 0,
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'uuid' => 'important',
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
],
|
||||
|
||||
// Omit a component. Should not match.
|
||||
@@ -120,6 +130,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
@@ -135,6 +146,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
'f' => 'f',
|
||||
],
|
||||
@@ -152,6 +164,24 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
],
|
||||
|
||||
// 0 should not match NULL.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
'_core' => 'foo',
|
||||
'uuid' => 'bar',
|
||||
'a' => 'a',
|
||||
'b' => NULL,
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
@@ -168,6 +198,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => 'e',
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
@@ -184,10 +215,29 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'c' => [
|
||||
'd' => 'd',
|
||||
'e' => FALSE,
|
||||
'empty' => [],
|
||||
],
|
||||
],
|
||||
FALSE,
|
||||
],
|
||||
|
||||
// Add an empty array at top, and remove at lower level. Should still
|
||||
// match.
|
||||
[
|
||||
$base,
|
||||
[
|
||||
'_core' => 'foo',
|
||||
'uuid' => 'bar',
|
||||
'a' => 'a',
|
||||
'b' => 0,
|
||||
'c' => [
|
||||
'd' => TRUE,
|
||||
'e' => FALSE,
|
||||
],
|
||||
'empty_two' => [],
|
||||
],
|
||||
TRUE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -201,6 +251,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'id_to_remove' => 'test.remove.id',
|
||||
'type' => 'old_type',
|
||||
'true_value' => TRUE,
|
||||
'null_value' => NULL,
|
||||
'nested_array' => [
|
||||
'flat_array' => [
|
||||
'value2',
|
||||
@@ -216,6 +267,7 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'id' => 'test.config.id',
|
||||
'type' => 'new_type',
|
||||
'true_value' => FALSE,
|
||||
'null_value' => FALSE,
|
||||
'nested_array' => [
|
||||
'flat_array' => [
|
||||
'value2',
|
||||
@@ -284,12 +336,14 @@ class ConfigDifferTest extends UnitTestCase {
|
||||
'orig' => [
|
||||
'nested_array::flat_array::1 : value1',
|
||||
'nested_array::flat_array::2 : value3',
|
||||
'true_value : 1',
|
||||
'null_value : null',
|
||||
'true_value : true',
|
||||
'type : old_type',
|
||||
],
|
||||
'closing' => [
|
||||
'nested_array::flat_array::1 : value3',
|
||||
'true_value : ',
|
||||
'null_value : false',
|
||||
'true_value : false',
|
||||
'type : new_type',
|
||||
],
|
||||
],
|
||||
|
||||
+177
-149
@@ -2,169 +2,73 @@
|
||||
|
||||
namespace Drupal\Tests\config_update\Unit;
|
||||
|
||||
use Drupal\config_update\ConfigLister;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the \Drupal\config_update\ConfigLister class.
|
||||
* Tests the \Drupal\config_update\ConfigListerWithProviders class.
|
||||
*
|
||||
* The methods from \Drupal\config_update\ConfigLister are also tested.
|
||||
*
|
||||
* @group config_update
|
||||
*
|
||||
* @coversDefaultClass \Drupal\config_update\ConfigLister
|
||||
* @coversDefaultClass \Drupal\config_update\ConfigListerWithProviders
|
||||
*/
|
||||
class ConfigListerTest extends UnitTestCase {
|
||||
class ConfigListerTest extends ConfigUpdateUnitTestBase {
|
||||
|
||||
/**
|
||||
* The config lister to test.
|
||||
*
|
||||
* @var \Drupal\config_update\ConfigLister
|
||||
* @var \Drupal\config_update\ConfigListerWithProviders
|
||||
*/
|
||||
protected $configLister;
|
||||
|
||||
/**
|
||||
* The mocked entity definition information.
|
||||
* List of configuration by provider in the mocks.
|
||||
*
|
||||
* @var string[]
|
||||
* This is an array whose keys are provider names, and whose values are
|
||||
* each an array containing the provider type, the name of one config item
|
||||
* mocked to be in config/install, and one in config/optional.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $entityDefinitionInformation;
|
||||
protected $configProviderList = [
|
||||
'foo_module' => ['module', 'foo.barbaz.one', 'foo.barbaz.two'],
|
||||
'foo_theme' => ['theme', 'foo.bar.one', 'foo.bar.two'],
|
||||
'standard' => ['profile', 'baz.bar.one', 'baz.bar.two'],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->configLister = new ConfigLister($this->getEntityManagerMock(), $this->getConfigStorageMock('active'), $this->getConfigStorageMock('extension'), $this->getConfigStorageMock('optional'));
|
||||
$lister = $this->getMockBuilder('Drupal\config_update\ConfigListerWithProviders')
|
||||
->setConstructorArgs([
|
||||
$this->getEntityManagerMock(),
|
||||
$this->getConfigStorageMock('active'),
|
||||
$this->getConfigStorageMock('extension'),
|
||||
$this->getConfigStorageMock('optional'),
|
||||
$this->getModuleHandlerMock(),
|
||||
$this->getThemeHandlerMock(),
|
||||
])
|
||||
->setMethods(['listProvidedItems', 'getProfileName'])
|
||||
->getMock();
|
||||
|
||||
$lister->method('getProfileName')
|
||||
->willReturn('standard');
|
||||
|
||||
$map = [];
|
||||
foreach ($this->configProviderList as $provider => $info) {
|
||||
// Info has: [type, install storage item, optional storage item].
|
||||
// Map needs: [type, provider name, isOptional, [config items]].
|
||||
$map[] = [$info[0], $provider, FALSE, [$info[1]]];
|
||||
$map[] = [$info[0], $provider, TRUE, [$info[2]]];
|
||||
}
|
||||
$lister->method('listProvidedItems')
|
||||
->will($this->returnValueMap($map));
|
||||
|
||||
$this->configLister = $lister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock entity manager for the test.
|
||||
*/
|
||||
protected function getEntityManagerMock() {
|
||||
// Make a list of fake entity definitions. Make sure they are not sorted,
|
||||
// to test that the methods sort them. Also make sure there are a couple
|
||||
// with prefixes that are subsets of each other.
|
||||
$this->entityDefinitionInformation = [
|
||||
['prefix' => 'foo.bar', 'type' => 'foo'],
|
||||
['prefix' => 'foo.barbaz', 'type' => 'bar'],
|
||||
['prefix' => 'baz.foo', 'type' => 'baz'],
|
||||
];
|
||||
|
||||
$definitions = [];
|
||||
foreach ($this->entityDefinitionInformation as $info) {
|
||||
$def = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityTypeInterface')->getMock();
|
||||
$def
|
||||
->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->willReturn($info['prefix']);
|
||||
$def
|
||||
->expects($this->any())
|
||||
->method('isSubclassOf')
|
||||
->willReturn(TRUE);
|
||||
|
||||
$def->getConfigPrefix();
|
||||
|
||||
$definitions[$info['type']] = $def;
|
||||
}
|
||||
|
||||
$manager = $this->getMockBuilder('Drupal\Core\Entity\EntityTypeManagerInterface')->getMock();
|
||||
$manager
|
||||
->method('getDefinitions')
|
||||
->willReturn($definitions);
|
||||
|
||||
return($manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock config storage object for the test.
|
||||
*
|
||||
* @param string $type
|
||||
* Type of storage object to return: 'active', 'extension', or 'optional'.
|
||||
*/
|
||||
protected function getConfigStorageMock($type) {
|
||||
if ($type == 'active') {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\StorageInterface')->getMock();
|
||||
|
||||
// The only use of the read() method on active storage is
|
||||
// with the core.extension config, to get the profile name.
|
||||
$storage
|
||||
->method('read')
|
||||
->willReturn(['profile' => 'standard']);
|
||||
|
||||
$map = [
|
||||
['foo.bar', ['foo.bar.one', 'foo.bar.two', 'foo.bar.three']],
|
||||
['foo.barbaz', ['foo.barbaz.four', 'foo.barbaz.five', 'foo.barbaz.six']],
|
||||
['baz.foo'], [],
|
||||
['',
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.three',
|
||||
'foo.barbaz.four',
|
||||
'foo.barbaz.five',
|
||||
'foo.barbaz.six',
|
||||
'something.else',
|
||||
'another.one',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($map));
|
||||
}
|
||||
elseif ($type == 'extension') {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\ExtensionInstallStorage')->disableOriginalConstructor()->getMock();
|
||||
$storage
|
||||
->method('getComponentNames')
|
||||
->willReturn([
|
||||
'foo.bar.one' => 'ignored',
|
||||
'foo.bar.two' => 'ignored',
|
||||
'foo.bar.seven' => 'ignored',
|
||||
'foo.barnot.three' => 'ignored',
|
||||
'something.else' => 'ignored',
|
||||
]);
|
||||
|
||||
$map = [
|
||||
['foo.bar', ['foo.bar.one', 'foo.bar.two', 'foo.bar.seven']],
|
||||
['baz.foo'], [],
|
||||
['',
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.seven',
|
||||
'foo.barbaz.four',
|
||||
'foo.barnot.three',
|
||||
'something.else',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($map));
|
||||
}
|
||||
else {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\ExtensionInstallStorage')->disableOriginalConstructor()->getMock();
|
||||
$storage
|
||||
->method('getComponentNames')
|
||||
->willReturn([
|
||||
'foo.barbaz.four' => 'ignored',
|
||||
]);
|
||||
|
||||
$map = [
|
||||
['foo.bar'], [],
|
||||
['foo.barbaz', ['foo.barbaz.four']],
|
||||
['', ['foo.barbaz.four']],
|
||||
];
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($map));
|
||||
}
|
||||
return $storage;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigLister::listConfig
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::listConfig
|
||||
* @dataProvider listConfigProvider
|
||||
*/
|
||||
public function testListConfig($a, $b, $expected) {
|
||||
@@ -176,12 +80,8 @@ class ConfigListerTest extends UnitTestCase {
|
||||
*/
|
||||
public function listConfigProvider() {
|
||||
return [
|
||||
// Arguments are $list_type, $name.
|
||||
// We cannot really test the extension types here, because they rely
|
||||
// on the going out to the file system to find out what config objects
|
||||
// are there. This is too complex to mock. It is tested in the tests for
|
||||
// the report output in the config_update_ui module tests. Anyway, we
|
||||
// can test the other types.
|
||||
// Arguments are $list_type, $name, and return value is that list of
|
||||
// configuration in active, extension, and optional storage.
|
||||
['type', 'system.all',
|
||||
[
|
||||
[
|
||||
@@ -220,11 +120,59 @@ class ConfigListerTest extends UnitTestCase {
|
||||
],
|
||||
],
|
||||
['type', 'unknown.type', [[], [], []]],
|
||||
['profile', 'dummy',
|
||||
[
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.three',
|
||||
'foo.barbaz.four',
|
||||
'foo.barbaz.five',
|
||||
'foo.barbaz.six',
|
||||
'something.else',
|
||||
'another.one',
|
||||
],
|
||||
['baz.bar.one'],
|
||||
['baz.bar.two'],
|
||||
],
|
||||
],
|
||||
['module', 'foo_module',
|
||||
[
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.three',
|
||||
'foo.barbaz.four',
|
||||
'foo.barbaz.five',
|
||||
'foo.barbaz.six',
|
||||
'something.else',
|
||||
'another.one',
|
||||
],
|
||||
['foo.barbaz.one'],
|
||||
['foo.barbaz.two'],
|
||||
],
|
||||
],
|
||||
['theme', 'foo_theme',
|
||||
[
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.three',
|
||||
'foo.barbaz.four',
|
||||
'foo.barbaz.five',
|
||||
'foo.barbaz.six',
|
||||
'something.else',
|
||||
'another.one',
|
||||
],
|
||||
['foo.bar.one'],
|
||||
['foo.bar.two'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigLister::getType
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::getType
|
||||
*/
|
||||
public function testGetType() {
|
||||
$return = $this->configLister->getType('not_in_list');
|
||||
@@ -237,7 +185,7 @@ class ConfigListerTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigLister::getTypeByPrefix
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::getTypeByPrefix
|
||||
*/
|
||||
public function testGetTypeByPrefix() {
|
||||
$return = $this->configLister->getTypeByPrefix('not_in_list');
|
||||
@@ -250,7 +198,7 @@ class ConfigListerTest extends UnitTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigLister::getTypeNameByConfigName
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::getTypeNameByConfigName
|
||||
*/
|
||||
public function testGetTypeNameByConfigName() {
|
||||
$return = $this->configLister->getTypeNameByConfigName('not_in_list');
|
||||
@@ -262,4 +210,84 @@ class ConfigListerTest extends UnitTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::listTypes
|
||||
*/
|
||||
public function testListTypes() {
|
||||
$return = $this->configLister->listTypes();
|
||||
// Should return an array in sorted order, of just the config entities
|
||||
// that $this->getEntityManagerMock() set up.
|
||||
$expected = ['bar' => 'foo.barbaz', 'baz' => 'baz.foo', 'foo' => 'foo.bar'];
|
||||
$this->assertEquals(array_keys($return), array_keys($expected));
|
||||
foreach ($return as $key => $definition) {
|
||||
$this->assertTrue($definition->entityClassImplements('Drupal\Core\Config\Entity\ConfigEntityInterface'));
|
||||
$this->assertEquals($definition->getConfigPrefix(), $expected[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::listProviders
|
||||
*/
|
||||
public function testListProviders() {
|
||||
// This method's return value is not sorted in any particular way.
|
||||
$return = $this->configLister->listProviders();
|
||||
$expected = [];
|
||||
foreach ($this->configProviderList as $provider => $info) {
|
||||
// Info has: [type, install storage item, optional storage item].
|
||||
// Expected needs: key is item name, value is [type, provider name].
|
||||
$expected[$info[1]] = [$info[0], $provider];
|
||||
$expected[$info[2]] = [$info[0], $provider];
|
||||
}
|
||||
ksort($return);
|
||||
ksort($expected);
|
||||
$this->assertEquals($return, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::getConfigProvider
|
||||
* @dataProvider getConfigProviderProvider
|
||||
*/
|
||||
public function testGetConfigProvider($a, $expected) {
|
||||
$this->assertEquals($expected, $this->configLister->getConfigProvider($a));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testGetConfigProvider().
|
||||
*/
|
||||
public function getConfigProviderProvider() {
|
||||
$values = [];
|
||||
foreach ($this->configProviderList as $provider => $info) {
|
||||
// Info has: [type, install storage item, optional storage item].
|
||||
// Values needs: [item, [type, provider name]].
|
||||
$values[] = [$info[1], [$info[0], $provider]];
|
||||
$values[] = [$info[2], [$info[0], $provider]];
|
||||
}
|
||||
$values[] = ['not.a.config.item', NULL];
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigListerWithProviders::providerHasConfig
|
||||
* @dataProvider providerHasConfigProvider
|
||||
*/
|
||||
public function testProviderHasConfig($a, $b, $expected) {
|
||||
$this->assertEquals($expected, $this->configLister->providerHasConfig($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testProviderHasConfig().
|
||||
*/
|
||||
public function providerHasConfigProvider() {
|
||||
$values = [];
|
||||
foreach ($this->configProviderList as $provider => $info) {
|
||||
// Info has: [type, install storage item, optional storage item].
|
||||
// Values needs: [type, provider name, TRUE] for valid providers,
|
||||
// change the last to FALSE for invalid providers.
|
||||
$values[] = [$info[0], $provider, TRUE];
|
||||
$values[] = [$info[0], $provider . '_suffix', FALSE];
|
||||
}
|
||||
$values[] = ['invalid_type', 'foo_module', FALSE];
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\config_update\Unit;
|
||||
|
||||
use Drupal\config_update\ConfigReverter;
|
||||
use Drupal\config_update\ConfigRevertInterface;
|
||||
use Drupal\config_update\ConfigDeleteInterface;
|
||||
|
||||
/**
|
||||
* Tests the \Drupal\config_update\ConfigReverter class.
|
||||
*
|
||||
* @group config_update
|
||||
*
|
||||
* @coversDefaultClass \Drupal\config_update\ConfigReverter
|
||||
*/
|
||||
class ConfigReverterTest extends ConfigUpdateUnitTestBase {
|
||||
|
||||
/**
|
||||
* The config reverter to test.
|
||||
*
|
||||
* @var \Drupal\config_update\ConfigReverter
|
||||
*/
|
||||
protected $configReverter;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->configReverter = new ConfigReverter(
|
||||
$this->getEntityManagerMock(),
|
||||
$this->getConfigStorageMock('active'),
|
||||
$this->getConfigStorageMock('extension'),
|
||||
$this->getConfigStorageMock('optional'),
|
||||
$this->getConfigFactoryMock(),
|
||||
$this->getEventDispatcherMock());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigReverter::getFromActive
|
||||
* @dataProvider getFromActiveProvider
|
||||
*/
|
||||
public function testGetFromActive($a, $b, $expected) {
|
||||
$this->assertEquals($expected, $this->configReverter->getFromActive($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testGetFromActive().
|
||||
*/
|
||||
public function getFromActiveProvider() {
|
||||
return [
|
||||
// Arguments are $type, $name, and return value is the config.
|
||||
// Some config items that are already prefixed.
|
||||
['', 'foo.bar.one', ['foo.bar.one' => 'active', 'id' => 'one']],
|
||||
['system.simple', 'foo.bar.one',
|
||||
['foo.bar.one' => 'active', 'id' => 'one'],
|
||||
],
|
||||
// Config item with a defined entity definition prefix. Entity type 'foo'
|
||||
// has prefix 'foo.bar'.
|
||||
['foo', 'one', ['foo.bar.one' => 'active', 'id' => 'one']],
|
||||
// Unknown type. This should not generate a call into the config read,
|
||||
// so should not return the known value.
|
||||
['unknown', 'foo.bar.one', FALSE],
|
||||
// Missing configuration. Config mock is configured to return FALSE for
|
||||
// this particular config name.
|
||||
['system.simple', 'missing', FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigReverter::getFromExtension
|
||||
* @dataProvider getFromExtensionProvider
|
||||
*/
|
||||
public function testGetFromExtension($a, $b, $expected) {
|
||||
$this->assertEquals($expected, $this->configReverter->getFromExtension($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testGetFromExtension().
|
||||
*/
|
||||
public function getFromExtensionProvider() {
|
||||
return [
|
||||
// Arguments are $type, $name, and return value is the config.
|
||||
// Some config items that are already prefixed, and exist in the mock
|
||||
// extension storage.
|
||||
['', 'in.extension', ['in.extension' => 'extension']],
|
||||
['system.simple', 'in.extension', ['in.extension' => 'extension']],
|
||||
// Config item with a defined entity definition prefix. Entity type 'foo'
|
||||
// has prefix 'foo.bar'.
|
||||
['foo', 'one', ['foo.bar.one' => 'extension', 'id' => 'one']],
|
||||
// One that exists in both extension and optional storage.
|
||||
['system.simple', 'in.both', ['in.both' => 'extension']],
|
||||
// One that exists only in optional storage.
|
||||
['system.simple', 'in.optional', ['in.optional' => 'optional']],
|
||||
// Unknown type. This should not generate a call into the config read,
|
||||
// so should not return the known value.
|
||||
['unknown', 'in.extension', FALSE],
|
||||
// Missing configuration. Storage mock is configured to return FALSE for
|
||||
// this particular config name.
|
||||
['system.simple', 'missing2', FALSE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigReverter::import
|
||||
* @dataProvider importProvider
|
||||
*/
|
||||
public function testImport($type, $name, $config_name, $expected, $config_before, $config_after) {
|
||||
// Clear dispatch log and set pre-config.
|
||||
$this->dispatchedEvents = [];
|
||||
if ($config_name) {
|
||||
$this->configStorage[$config_name] = $config_before;
|
||||
}
|
||||
$save_config = $this->configStorage;
|
||||
|
||||
// Call the importer and test the Boolean result.
|
||||
$result = $this->configReverter->import($type, $name);
|
||||
$this->assertEquals($result, $expected);
|
||||
|
||||
if ($result) {
|
||||
// Verify that the config is correct after import, and logging worked.
|
||||
$this->assertEquals($this->configStorage[$config_name], $config_after);
|
||||
$this->assertEquals(count($this->dispatchedEvents), 1);
|
||||
$this->assertEquals($this->dispatchedEvents[0][0], ConfigRevertInterface::IMPORT);
|
||||
}
|
||||
else {
|
||||
// Verify that the config didn't change and no events were logged.
|
||||
$this->assertEquals($this->configStorage, $save_config);
|
||||
$this->assertEquals(count($this->dispatchedEvents), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testImport().
|
||||
*/
|
||||
public function importProvider() {
|
||||
return [
|
||||
// Elements: type, name, config name, return value,
|
||||
// config to set up before, config expected after. See also
|
||||
// getFromExtensionProvider().
|
||||
[
|
||||
'system.simple',
|
||||
'in.extension',
|
||||
'in.extension',
|
||||
TRUE,
|
||||
['in.extension' => 'before'],
|
||||
['in.extension' => 'extension', '_core' => 'core_for_in.extension'],
|
||||
],
|
||||
[
|
||||
'foo',
|
||||
'one',
|
||||
'foo.bar.one',
|
||||
TRUE,
|
||||
['foo.bar.one' => 'before', 'id' => 'one'],
|
||||
[
|
||||
'foo.bar.one' => 'extension',
|
||||
'id' => 'one',
|
||||
'_core' => 'core_for_foo.bar.one',
|
||||
],
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'in.both',
|
||||
'in.both',
|
||||
TRUE,
|
||||
['in.both' => 'before'],
|
||||
['in.both' => 'extension', '_core' => 'core_for_in.both'],
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'in.optional',
|
||||
'in.optional',
|
||||
TRUE,
|
||||
['in.optional' => 'before'],
|
||||
['in.optional' => 'optional', '_core' => 'core_for_in.optional'],
|
||||
],
|
||||
[
|
||||
'unknown',
|
||||
'in.extension',
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'missing2',
|
||||
'missing2',
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigReverter::revert
|
||||
* @dataProvider revertProvider
|
||||
*/
|
||||
public function testRevert($type, $name, $config_name, $expected, $config_before, $config_after) {
|
||||
// Clear dispatch log and set pre-config.
|
||||
$this->dispatchedEvents = [];
|
||||
if ($config_name) {
|
||||
$this->configStorage[$config_name] = $config_before;
|
||||
}
|
||||
$save_config = $this->configStorage;
|
||||
|
||||
// Call the reverter and test the Boolean result.
|
||||
$result = $this->configReverter->revert($type, $name);
|
||||
$this->assertEquals($result, $expected);
|
||||
|
||||
if ($result) {
|
||||
// Verify that the config is correct after revert, and logging worked.
|
||||
$this->assertEquals($this->configStorage[$config_name], $config_after);
|
||||
$this->assertEquals(count($this->dispatchedEvents), 1);
|
||||
$this->assertEquals($this->dispatchedEvents[0][0], ConfigRevertInterface::REVERT);
|
||||
}
|
||||
else {
|
||||
// Verify that the config didn't change and no events were logged.
|
||||
$this->assertEquals($this->configStorage, $save_config);
|
||||
$this->assertEquals(count($this->dispatchedEvents), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testRevert().
|
||||
*/
|
||||
public function revertProvider() {
|
||||
return [
|
||||
// Elements: type, name, config name, return value,
|
||||
// config to set up before, config expected after. See also
|
||||
// getFromExtensionProvider().
|
||||
[
|
||||
'system.simple',
|
||||
'in.extension',
|
||||
'in.extension',
|
||||
TRUE,
|
||||
['in.extension' => 'active'],
|
||||
['in.extension' => 'extension', '_core' => 'core_for_in.extension'],
|
||||
],
|
||||
[
|
||||
'foo',
|
||||
'one',
|
||||
'foo.bar.one',
|
||||
TRUE,
|
||||
['foo.bar.one' => 'active', 'id' => 'one'],
|
||||
[
|
||||
'foo.bar.one' => 'extension',
|
||||
'id' => 'one',
|
||||
'_core' => 'core_for_foo.bar.one',
|
||||
],
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'in.both',
|
||||
'in.both',
|
||||
TRUE,
|
||||
['in.both' => 'active'],
|
||||
['in.both' => 'extension', '_core' => 'core_for_in.both'],
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'in.optional',
|
||||
'in.optional',
|
||||
TRUE,
|
||||
['in.optional' => 'active'],
|
||||
['in.optional' => 'optional', '_core' => 'core_for_in.optional'],
|
||||
],
|
||||
[
|
||||
'unknown',
|
||||
'in.extension',
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
// Missing from extension storage.
|
||||
[
|
||||
'system.simple',
|
||||
'missing2',
|
||||
'missing2',
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
// Present in extension storage but missing from active storage.
|
||||
[
|
||||
'system.simple',
|
||||
'another',
|
||||
'another',
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Drupal\config_update\ConfigReverter::delete
|
||||
* @dataProvider deleteProvider
|
||||
*/
|
||||
public function testDelete($type, $name, $config_name, $expected) {
|
||||
// Clear dispatch log.
|
||||
$this->dispatchedEvents = [];
|
||||
$save_config = $this->configStorage;
|
||||
|
||||
// Call the deleteer and test the Boolean result.
|
||||
$result = $this->configReverter->delete($type, $name);
|
||||
$this->assertEquals($result, $expected);
|
||||
|
||||
if ($result) {
|
||||
// Verify that the config is missing after delete, and logging worked.
|
||||
$this->assertTrue(!isset($this->configStorage[$config_name]));
|
||||
$this->assertEquals(count($this->dispatchedEvents), 1);
|
||||
$this->assertEquals($this->dispatchedEvents[0][0], ConfigDeleteInterface::DELETE);
|
||||
}
|
||||
else {
|
||||
// Verify that the config didn't change and no events were logged.
|
||||
$this->assertEquals($this->configStorage, $save_config);
|
||||
$this->assertEquals(count($this->dispatchedEvents), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for self:testDelete().
|
||||
*/
|
||||
public function deleteProvider() {
|
||||
return [
|
||||
// Elements: type, name, config name, return value.
|
||||
[
|
||||
'system.simple',
|
||||
'in.extension',
|
||||
'in.extension',
|
||||
TRUE,
|
||||
],
|
||||
[
|
||||
'foo',
|
||||
'one',
|
||||
'foo.bar.one',
|
||||
TRUE,
|
||||
],
|
||||
[
|
||||
'unknown',
|
||||
'in.extension',
|
||||
FALSE,
|
||||
FALSE,
|
||||
],
|
||||
[
|
||||
'system.simple',
|
||||
'missing2',
|
||||
'missing2',
|
||||
FALSE,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
+547
@@ -0,0 +1,547 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\config_update\Unit;
|
||||
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Base class for unit testing in Config Update Manager.
|
||||
*
|
||||
* This class provides some mock classes for unit testing.
|
||||
*/
|
||||
abstract class ConfigUpdateUnitTestBase extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mocked entity definition information.
|
||||
*
|
||||
* They are not sorted, to test that the methods sort them. Also there are a
|
||||
* couple with prefixes that are subsets of each other.
|
||||
*
|
||||
* @var string[]
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::getEntityManagerMock().
|
||||
*/
|
||||
protected $entityDefinitionInformation = [
|
||||
['prefix' => 'foo.bar', 'type' => 'foo'],
|
||||
['prefix' => 'foo.barbaz', 'type' => 'bar'],
|
||||
['prefix' => 'baz.foo', 'type' => 'baz'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a mock entity manager for the test.
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::entityDefinitionInformation
|
||||
*/
|
||||
protected function getEntityManagerMock() {
|
||||
$definitions = [];
|
||||
$map = [];
|
||||
foreach ($this->entityDefinitionInformation as $info) {
|
||||
$def = $this->getMockBuilder('Drupal\Core\Config\Entity\ConfigEntityTypeInterface')->getMock();
|
||||
$def
|
||||
->expects($this->any())
|
||||
->method('getConfigPrefix')
|
||||
->willReturn($info['prefix']);
|
||||
$def
|
||||
->expects($this->any())
|
||||
->method('entityClassImplements')
|
||||
->willReturn(TRUE);
|
||||
|
||||
$def
|
||||
->method('getKey')
|
||||
->willReturn('id');
|
||||
|
||||
$def->getConfigPrefix();
|
||||
|
||||
$definitions[$info['type']] = $def;
|
||||
$map[] = [$info['type'], FALSE, $def];
|
||||
$map[] = [$info['type'], TRUE, $def];
|
||||
}
|
||||
|
||||
// Add in a content entity definition, which shouldn't be recognized by the
|
||||
// config lister class.
|
||||
$def = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityTypeInterface')->getMock();
|
||||
$def
|
||||
->expects($this->any())
|
||||
->method('entityClassImplements')
|
||||
->willReturn(FALSE);
|
||||
$definitions['content_entity'] = $def;
|
||||
|
||||
$manager = $this->getMockBuilder('Drupal\Core\Entity\EntityTypeManagerInterface')->getMock();
|
||||
$manager
|
||||
->method('getDefinitions')
|
||||
->willReturn($definitions);
|
||||
|
||||
$manager
|
||||
->method('getDefinition')
|
||||
->will($this->returnValueMap($map));
|
||||
|
||||
$manager
|
||||
->method('getStorage')
|
||||
->will($this->returnCallback([$this, 'mockGetStorage']));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the getStorage() method for the entity manager.
|
||||
*/
|
||||
public function mockGetStorage($entity_type) {
|
||||
// Figure out the config prefix for this entity type.
|
||||
$prefix = '';
|
||||
foreach ($this->entityDefinitionInformation as $info) {
|
||||
if ($info['type'] == $entity_type) {
|
||||
$prefix = $info['prefix'];
|
||||
}
|
||||
}
|
||||
|
||||
// This is used in ConfigReverter::import(). Although it is supposed to
|
||||
// be entity storage, we'll use our mock config object instead.
|
||||
return new MockConfig('', $prefix, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of active configuration information for mocking.
|
||||
*
|
||||
* Array structure: Each element is an array whose first element is a
|
||||
* provider name, and second is an array of config items it provides.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::getConfigStorageMock()
|
||||
*/
|
||||
protected $configStorageActiveInfo = [
|
||||
['foo.bar', ['foo.bar.one', 'foo.bar.two', 'foo.bar.three']],
|
||||
['foo.barbaz', ['foo.barbaz.four', 'foo.barbaz.five', 'foo.barbaz.six']],
|
||||
['baz.foo', []],
|
||||
['',
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.three',
|
||||
'foo.barbaz.four',
|
||||
'foo.barbaz.five',
|
||||
'foo.barbaz.six',
|
||||
'something.else',
|
||||
'another.one',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Array of extension configuration information for mocking.
|
||||
*
|
||||
* Array structure: Each element is an array whose first element is a
|
||||
* provider name, and second is an array of config items it provides.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::getConfigStorageMock()
|
||||
*/
|
||||
protected $configStorageExtensionInfo = [
|
||||
['foo.bar', ['foo.bar.one', 'foo.bar.two', 'foo.bar.seven']],
|
||||
['baz.foo', []],
|
||||
// This next item is assumed to be element 2 of the array. If not, you
|
||||
// will need to change ConfigUpdateUnitTestBase::getConfigStorageMock().
|
||||
['',
|
||||
[
|
||||
'foo.bar.one',
|
||||
'foo.bar.two',
|
||||
'foo.bar.seven',
|
||||
'foo.barbaz.four',
|
||||
'foo.barnot.three',
|
||||
'something.else',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Array of optional configuration information for mocking.
|
||||
*
|
||||
* Array structure: Each element is an array whose first element is a
|
||||
* provider name, and second is an array of config items it provides.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::getConfigStorageMock()
|
||||
*/
|
||||
protected $configStorageOptionalInfo = [
|
||||
['foo.bar', []],
|
||||
['foo.barbaz', ['foo.barbaz.four']],
|
||||
// This next item is assumed to be element 2 of the array. If not, you
|
||||
// will need to change ConfigUpdateUnitTestBase::getConfigStorageMock().
|
||||
['', ['foo.barbaz.four']],
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a mock config storage object for the test.
|
||||
*
|
||||
* @param string $type
|
||||
* Type of storage object to return: 'active', 'extension', or 'optional'.
|
||||
* In active storage, the read() method is mocked to assume you are reading
|
||||
* core.extension to get the profile name, so it returns that information.
|
||||
* For extension and optional storage, the getComponentNames() method is
|
||||
* mocked, and for all storages, the listAll() method is mocked.
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::configStorageActiveInfo
|
||||
* @see ConfigUpdateUnitTestBase::configStorageExtensionInfo
|
||||
* @see ConfigUpdateUnitTestBase::configStorageOptionalInfo
|
||||
*/
|
||||
protected function getConfigStorageMock($type) {
|
||||
if ($type == 'active') {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\StorageInterface')->getMock();
|
||||
|
||||
// Various tests assume various values of configuration that need to be
|
||||
// read from active storage.
|
||||
$map = [
|
||||
['core.extension', ['profile' => 'standard']],
|
||||
['foo.bar.one', ['foo.bar.one' => 'active', 'id' => 'one']],
|
||||
['missing', FALSE],
|
||||
['in.extension',
|
||||
['in.extension' => 'active', '_core' => 'core_for_in.extension'],
|
||||
],
|
||||
['in.both', ['in.both' => 'active']],
|
||||
['in.optional', ['in.optional' => 'active']],
|
||||
];
|
||||
$storage
|
||||
->method('read')
|
||||
->will($this->returnValueMap($map));
|
||||
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($this->configStorageActiveInfo));
|
||||
}
|
||||
elseif ($type == 'extension') {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\ExtensionInstallStorage')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$value = [];
|
||||
foreach ($this->configStorageExtensionInfo[2][1] as $item) {
|
||||
$value[$item] = 'ignored';
|
||||
}
|
||||
$storage
|
||||
->method('getComponentNames')
|
||||
->willReturn($value);
|
||||
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($this->configStorageExtensionInfo));
|
||||
$map = [
|
||||
['in.extension', ['in.extension' => 'extension']],
|
||||
['in.both', ['in.both' => 'extension']],
|
||||
['in.optional', FALSE],
|
||||
['foo.bar.one', ['foo.bar.one' => 'extension', 'id' => 'one']],
|
||||
['another', ['another' => 'extension', 'id' => 'one']],
|
||||
['missing2', FALSE],
|
||||
];
|
||||
$storage
|
||||
->method('read')
|
||||
->will($this->returnValueMap($map));
|
||||
|
||||
}
|
||||
else {
|
||||
$storage = $this->getMockBuilder('Drupal\Core\Config\ExtensionInstallStorage')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$value = [];
|
||||
foreach ($this->configStorageOptionalInfo[2][1] as $item) {
|
||||
$value[$item] = 'ignored';
|
||||
}
|
||||
$storage
|
||||
->method('getComponentNames')
|
||||
->willReturn($value);
|
||||
|
||||
$storage
|
||||
->method('listAll')
|
||||
->will($this->returnValueMap($this->configStorageOptionalInfo));
|
||||
|
||||
$map = [
|
||||
['in.optional', ['in.optional' => 'optional']],
|
||||
['in.both', ['in.both' => 'optional']],
|
||||
['missing2', FALSE],
|
||||
];
|
||||
$storage
|
||||
->method('read')
|
||||
->will($this->returnValueMap($map));
|
||||
}
|
||||
return $storage;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock module handler for the test.
|
||||
*/
|
||||
protected function getModuleHandlerMock() {
|
||||
$manager = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')->getMock();
|
||||
$manager->method('getModuleList')
|
||||
->willReturn(['foo_module' => '', 'standard' => '']);
|
||||
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock theme handler for the test.
|
||||
*/
|
||||
protected function getThemeHandlerMock() {
|
||||
$manager = $this->getMockBuilder('Drupal\Core\Extension\ThemeHandlerInterface')->getMock();
|
||||
$manager->method('listInfo')
|
||||
->willReturn(['foo_theme' => '']);
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock string translation class for the test.
|
||||
*/
|
||||
protected function getTranslationMock() {
|
||||
$translation = $this->getMockBuilder('Drupal\Core\StringTranslation\TranslationInterface')->getMock();
|
||||
$translation
|
||||
->method('translateString')
|
||||
->will($this->returnCallback([$this, 'mockTranslate']));
|
||||
return $translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the translateString() method for the string translation mock object.
|
||||
*
|
||||
* @param \Drupal\Core\StringTranslation\TranslatableMarkup $input
|
||||
* Object to translate.
|
||||
*
|
||||
* @return string
|
||||
* The untranslated string from $input.
|
||||
*/
|
||||
public function mockTranslate(TranslatableMarkup $input) {
|
||||
return $input->getUntranslatedString();
|
||||
}
|
||||
|
||||
/**
|
||||
* List of mock-dispatched events.
|
||||
*
|
||||
* Each element of the array is the call parameters to dispatchEvent() in
|
||||
* the mocked dispatch class: name and event instance.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @see ConfigUpdateUnitTestBase::getEventDispatcherMock()
|
||||
*/
|
||||
protected $dispatchedEvents = [];
|
||||
|
||||
/**
|
||||
* Mocks the event dispatcher service.
|
||||
*
|
||||
* Stores dispatched events in ConfigUpdateUnitTestBase::dispatchedEvents.
|
||||
*/
|
||||
protected function getEventDispatcherMock() {
|
||||
$event = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
|
||||
$event
|
||||
->method('dispatch')
|
||||
->will($this->returnCallback([$this, 'mockDispatch']));
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks event dispatch.
|
||||
*
|
||||
* For \Symfony\Component\EventDispatcher\EventDispatchInterface::dispatch().
|
||||
*/
|
||||
public function mockDispatch($name, Event $event = NULL) {
|
||||
$this->dispatchedEvents[] = [$name, $event];
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock config storage for the mock config factory.
|
||||
*
|
||||
* This is actually managed by the MockConfig class in this file.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $configStorage = [];
|
||||
|
||||
/**
|
||||
* Gets the value of the mocked config storage.
|
||||
*/
|
||||
public function getConfigStorage() {
|
||||
return $this->configStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the mocked config storage.
|
||||
*/
|
||||
public function setConfigStorage($values) {
|
||||
$this->configStorage = $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mock config factory class for the test.
|
||||
*/
|
||||
protected function getConfigFactoryMock() {
|
||||
$config = $this->getMockBuilder('Drupal\Core\Config\ConfigFactoryInterface')->getMock();
|
||||
$config
|
||||
->method('getEditable')
|
||||
->will($this->returnCallback([$this, 'mockGetEditable']));
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the getEditable() method for the mock config factory.
|
||||
*
|
||||
* @param string $name
|
||||
* Name of the config object to get an editable object for.
|
||||
*
|
||||
* @return MockConfig
|
||||
* Editable mock config object.
|
||||
*/
|
||||
public function mockGetEditable($name) {
|
||||
return new MockConfig($name, '', $this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock class for mutable configuration, config entity, and entity storage.
|
||||
*/
|
||||
class MockConfig {
|
||||
|
||||
/**
|
||||
* Name of the config.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = '';
|
||||
|
||||
/**
|
||||
* Prefix for the entity type being mocked, for entity storage mocking.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entityPrefix = '';
|
||||
|
||||
/**
|
||||
* Test class this comes from.
|
||||
*
|
||||
* @var \Drupal\Tests\config_update\Unit\ConfigUpdateUnitTestBase
|
||||
*/
|
||||
protected $test;
|
||||
|
||||
/**
|
||||
* Current value of the configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $value = '';
|
||||
|
||||
/**
|
||||
* Constructs a mock config object.
|
||||
*
|
||||
* @param string $name
|
||||
* Name of the config that is being mocked. Can be blank.
|
||||
* @param string $entity_prefix
|
||||
* Prefix for the entity type that is being mocked. Often blank.
|
||||
* @param \Drupal\Tests\config_update\Unit\ConfigUpdateUnitTestBase $test
|
||||
* Test class this comes from.
|
||||
*/
|
||||
public function __construct($name, $entity_prefix, ConfigUpdateUnitTestBase $test) {
|
||||
$this->name = $name;
|
||||
$this->entityPrefix = $entity_prefix;
|
||||
$this->test = $test;
|
||||
|
||||
$storage = $test->getConfigStorage();
|
||||
if ($name && isset($storage[$name])) {
|
||||
$value = $storage[$name];
|
||||
$value['is_new'] = FALSE;
|
||||
}
|
||||
else {
|
||||
$value['is_new'] = TRUE;
|
||||
}
|
||||
$value['_core'] = 'core_for_' . $name;
|
||||
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a component of the configuration value.
|
||||
*/
|
||||
public function get($key) {
|
||||
return isset($this->value[$key]) ? $this->value[$key] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a component of the configuration value.
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
$this->value[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entire configuration value.
|
||||
*/
|
||||
public function setData($value) {
|
||||
// Retain the _core key.
|
||||
$core = isset($this->value['_core']) ? $this->value['_core'] : '';
|
||||
$this->value = $value;
|
||||
if ($core) {
|
||||
$this->value['_core'] = $core;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the configuration.
|
||||
*/
|
||||
public function save() {
|
||||
$config = $this->test->getConfigStorage();
|
||||
$config[$this->name] = $this->value;
|
||||
$this->test->setConfigStorage($config);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the configuration.
|
||||
*/
|
||||
public function delete() {
|
||||
$config = $this->test->getConfigStorage();
|
||||
unset($config[$this->name]);
|
||||
$this->test->setConfigStorage($config);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the createFromStorageRecord() method from entity storage.
|
||||
*/
|
||||
public function createFromStorageRecord($values) {
|
||||
if (!$this->entityPrefix) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This is supposed to return an entity, but the only method we need is
|
||||
// save(), so instead set up and return this object.
|
||||
$this->name = $this->entityPrefix . '.' . $values['id'];
|
||||
$this->value = $values;
|
||||
$this->value['_core'] = 'core_for_' . $this->name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the updateFromStorageRecord() method from entity storage.
|
||||
*/
|
||||
public function updateFromStorageRecord($object, $values) {
|
||||
return $object->createFromStorageRecord($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks the load() method for entity storage.
|
||||
*/
|
||||
public function load($id) {
|
||||
$full_name = $this->entityPrefix . '.' . $id;
|
||||
$configs = $this->test->getConfigStorage();
|
||||
if (isset($configs[$full_name])) {
|
||||
$this->value = $configs[$full_name];
|
||||
$this->name = $full_name;
|
||||
$this->value['_core'] = 'core_for_' . $full_name;
|
||||
return $this;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user