updated contrib modules

This commit is contained in:
Bachir Soussi Chiadmi
2018-01-24 13:37:38 +01:00
parent f9374cf96d
commit c57b3644fe
126 changed files with 6835 additions and 905 deletions
@@ -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-09-18
version: '8.x-1.4'
# Information added by Drupal.org packaging script on 2017-12-05
version: '8.x-1.5'
core: '8.x'
project: 'config_update'
datestamp: 1505755746
datestamp: 1512514387
@@ -7,8 +7,8 @@ dependencies:
- config_update:config_update
- drupal:config
# Information added by Drupal.org packaging script on 2017-09-18
version: '8.x-1.4'
# Information added by Drupal.org packaging script on 2017-12-05
version: '8.x-1.5'
core: '8.x'
project: 'config_update'
datestamp: 1505755746
datestamp: 1512514387
@@ -12,9 +12,7 @@ config_update_ui.import:
path: '/admin/config/development/configuration/report/import/{config_type}/{config_name}'
defaults:
_title: 'Import'
_controller: '\Drupal\config_update_ui\Controller\ConfigUpdateController::import'
config_type: NULL
config_name: NULL
_form: '\Drupal\config_update_ui\Form\ConfigImportConfirmForm'
requirements:
_permission: 'import configuration'
@@ -112,26 +112,6 @@ class ConfigUpdateController extends ControllerBase {
);
}
/**
* Imports configuration from a module, theme, or profile.
*
* Configuration is assumed not to currently exist.
*
* @param string $config_type
* The type of configuration.
* @param string $config_name
* The name of the config item, without the prefix.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* Redirects to the updates report.
*/
public function import($config_type, $config_name) {
$this->configRevert->import($config_type, $config_name);
drupal_set_message($this->t('The configuration was imported.'));
return $this->redirect('config_update_ui.report');
}
/**
* Shows the diff between active and provided configuration.
*
@@ -8,6 +8,7 @@ use Drupal\Core\Url;
use Drupal\config_update\ConfigListInterface;
use Drupal\config_update\ConfigRevertInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Defines a confirmation form for deleting configuration.
@@ -81,9 +82,20 @@ class ConfigDeleteConfirmForm extends ConfirmFormBase {
}
else {
$definition = $this->configList->getType($this->type);
if (!$definition) {
// Make a 404 error if the type doesn't exist.
throw new NotFoundHttpException();
}
$type_label = $definition->get('label');
}
// To delete, the configuration item must exist in active storage. Check
// that and make a 404 error if not.
$active = $this->configRevert->getFromActive($this->type, $this->name);
if (!$active) {
throw new NotFoundHttpException();
}
return $this->t('Are you sure you want to delete the %type config %item?', ['%type' => $type_label, '%item' => $this->name]);
}
@@ -119,17 +131,6 @@ class ConfigDeleteConfirmForm extends ConfirmFormBase {
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$value = $this->configRevert->getFromActive($this->type, $this->name);
if (!$value) {
$form_state->setErrorByName('', $this->t('There is no configuration @type named @name to delete', ['@type' => $this->type, '@name' => $this->name]));
return;
}
}
/**
* {@inheritdoc}
*/
@@ -0,0 +1,146 @@
<?php
namespace Drupal\config_update_ui\Form;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\config_update\ConfigListInterface;
use Drupal\config_update\ConfigRevertInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Defines a confirmation form for importing configuration.
*/
class ConfigImportConfirmForm extends ConfirmFormBase {
/**
* The type of config being imported.
*
* @var string
*/
protected $type;
/**
* The name of the config item being imported, without the prefix.
*
* @var string
*/
protected $name;
/**
* The config lister.
*
* @var \Drupal\config_update\ConfigListInterface
*/
protected $configList;
/**
* The config reverter.
*
* @var \Drupal\config_update\ConfigRevertInterface
*/
protected $configRevert;
/**
* Constructs a ConfigImportConfirmForm object.
*
* @param \Drupal\config_update\ConfigListInterface $config_list
* The config lister.
* @param \Drupal\config_update\ConfigRevertInterface $config_update
* The config reverter.
*/
public function __construct(ConfigListInterface $config_list, ConfigRevertInterface $config_update) {
$this->configList = $config_list;
$this->configRevert = $config_update;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config_update.config_list'),
$container->get('config_update.config_update')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'config_import_confirm';
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
if ($this->type == 'system.simple') {
$type_label = $this->t('Simple configuration');
}
else {
$definition = $this->configList->getType($this->type);
if (!$definition) {
// Make a 404 error if the type doesn't exist.
throw new NotFoundHttpException();
}
$type_label = $definition->get('label');
}
// To import (as opposed to revert), the configuration item must exist in
// extension storage but not active storage, so check that, and make a 404
// error if not.
$extension = $this->configRevert->getFromExtension($this->type, $this->name);
$active = $this->configRevert->getFromActive($this->type, $this->name);
if (!$extension || $active) {
throw new NotFoundHttpException();
}
return $this->t('Are you sure you want to import the %type config %item from its source configuration?', ['%type' => $type_label, '%item' => $this->name]);
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
return new Url('config_update_ui.report');
}
/**
* {@inheritdoc}
*/
public function getDescription() {
return $this->t('Configuration will be added to your site. This action cannot be undone.');
}
/**
* {@inheritdoc}
*/
public function getConfirmText() {
return $this->t('Import');
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $config_type = NULL, $config_name = NULL) {
$this->type = $config_type;
$this->name = $config_name;
$form = parent::buildForm($form, $form_state);
return $form;
}
/**
* {@inheritdoc}
*/
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.'));
$form_state->setRedirectUrl($this->getCancelUrl());
}
}
@@ -8,6 +8,7 @@ use Drupal\Core\Url;
use Drupal\config_update\ConfigListInterface;
use Drupal\config_update\ConfigRevertInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Defines a confirmation form for reverting configuration.
@@ -81,9 +82,22 @@ class ConfigRevertConfirmForm extends ConfirmFormBase {
}
else {
$definition = $this->configList->getType($this->type);
if (!$definition) {
// Make a 404 error if the type doesn't exist.
throw new NotFoundHttpException();
}
$type_label = $definition->get('label');
}
// To revert (as opposed to import), the configuration item must exist in
// both active storage and extension storage, so check that and make a 404
// error if not.
$extension = $this->configRevert->getFromExtension($this->type, $this->name);
$active = $this->configRevert->getFromActive($this->type, $this->name);
if (!$extension || !$active) {
throw new NotFoundHttpException();
}
return $this->t('Are you sure you want to revert the %type config %item to its source configuration?', ['%type' => $type_label, '%item' => $this->name]);
}
@@ -119,17 +133,6 @@ class ConfigRevertConfirmForm extends ConfirmFormBase {
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
$value = $this->configRevert->getFromExtension($this->type, $this->name);
if (!$value) {
$form_state->setErrorByName('', $this->t('There is no configuration @type named @name to import', ['@type' => $this->type, '@name' => $this->name]));
return;
}
}
/**
* {@inheritdoc}
*/
@@ -106,6 +106,11 @@ class ConfigUpdateTest extends WebTestBase {
$this->assertText('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);
// Delete the user search page from the search UI and verify report for
// both the search page config type and user module.
$this->drupalGet('admin/config/search/pages');
@@ -130,10 +135,19 @@ class ConfigUpdateTest extends WebTestBase {
'views.view.who_s_online',
], ['changed']);
// 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);
// Verify that the delete URL doesn't work either.
$this->drupalGet('admin/config/development/configuration/report/delete/search_page/user_search');
$this->assertResponse(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');
$this->assertNoReport();
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
@@ -277,6 +291,7 @@ class ConfigUpdateTest extends WebTestBase {
$this->assertText('cannot be undone');
$this->drupalPostForm(NULL, [], 'Delete');
$this->assertText('The configuration was deleted');
// And verify the report again.
$this->drupalGet('admin/config/development/configuration/report/type/search_page');
$this->assertReport('Search page', [], [], [], []);
@@ -123,7 +123,7 @@ class ConfigLister implements ConfigListInterface {
public function getTypeNameByConfigName($name) {
$definitions = $this->listTypes();
foreach ($this->typesByPrefix as $prefix => $entity_type) {
if (strpos($name, $prefix) === 0) {
if (strpos($name, $prefix . '.') === 0) {
return $entity_type;
}
}
@@ -174,6 +174,12 @@ class ConfigLister implements ConfigListInterface {
break;
}
// This only seems to be a problem in unit tests, where a mock object
// is returning NULL instead of an empy array for some reason.
if (!is_array($optional_list)) {
$optional_list = [];
}
return [$active_list, $install_list, $optional_list];
}
@@ -211,7 +217,7 @@ class ConfigLister implements ConfigListInterface {
$list = array_combine($list, $list);
foreach ($list as $name) {
foreach ($prefixes as $prefix) {
if (strpos($name, $prefix) === 0) {
if (strpos($name, $prefix . '.') === 0) {
unset($list[$name]);
}
}
@@ -0,0 +1,265 @@
<?php
namespace Drupal\Tests\config_update\Unit;
use Drupal\config_update\ConfigLister;
use Drupal\Tests\UnitTestCase;
/**
* Tests the \Drupal\config_update\ConfigLister class.
*
* @group config_update
*
* @coversDefaultClass \Drupal\config_update\ConfigLister
*/
class ConfigListerTest extends UnitTestCase {
/**
* The config lister to test.
*
* @var \Drupal\config_update\ConfigLister
*/
protected $configLister;
/**
* The mocked entity definition information.
*
* @var string[]
*/
protected $entityDefinitionInformation;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->configLister = new ConfigLister($this->getEntityManagerMock(), $this->getConfigStorageMock('active'), $this->getConfigStorageMock('extension'), $this->getConfigStorageMock('optional'));
}
/**
* 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
* @dataProvider listConfigProvider
*/
public function testListConfig($a, $b, $expected) {
$this->assertEquals($expected, $this->configLister->listConfig($a, $b));
}
/**
* Data provider for self:testListConfig().
*/
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.
['type', 'system.all',
[
[
'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',
'foo.bar.seven',
'foo.barbaz.four',
'foo.barnot.three',
'something.else',
],
['foo.barbaz.four'],
],
],
['type', 'system.simple',
[
['something.else', 'another.one'],
['foo.barnot.three', 'something.else'],
[],
],
],
['type', 'foo',
[
['foo.bar.one', 'foo.bar.two', 'foo.bar.three'],
['foo.bar.one', 'foo.bar.two', 'foo.bar.seven'],
[],
],
],
['type', 'unknown.type', [[], [], []]],
];
}
/**
* @covers \Drupal\config_update\ConfigLister::getType
*/
public function testGetType() {
$return = $this->configLister->getType('not_in_list');
$this->assertNull($return);
foreach ($this->entityDefinitionInformation as $info) {
$return = $this->configLister->getType($info['type']);
$this->assertEquals($return->getConfigPrefix(), $info['prefix']);
}
}
/**
* @covers \Drupal\config_update\ConfigLister::getTypeByPrefix
*/
public function testGetTypeByPrefix() {
$return = $this->configLister->getTypeByPrefix('not_in_list');
$this->assertNull($return);
foreach ($this->entityDefinitionInformation as $info) {
$return = $this->configLister->getTypeByPrefix($info['prefix']);
$this->assertEquals($return->getConfigPrefix(), $info['prefix']);
}
}
/**
* @covers \Drupal\config_update\ConfigLister::getTypeNameByConfigName
*/
public function testGetTypeNameByConfigName() {
$return = $this->configLister->getTypeNameByConfigName('not_in_list');
$this->assertNull($return);
foreach ($this->entityDefinitionInformation as $info) {
$return = $this->configLister->getTypeNameByConfigName($info['prefix'] . '.something');
$this->assertEquals($return, $info['type']);
}
}
}